The servicemix-wsn2005 is a standard JBI Service Engine which implements the WS-Notification specification from Oasis.
While this article does not intend to be a review of the WS-Notification specification, here is a few terms you need to fully understand:
The current implementation has several limitations:
The WS-Notification SE can be used to provide publish/subscribe routing in the JBI bus. There are several usage:
The servicemix-wsn2005 accepts deployment of Service Units.
The requests will be started in this very order, so that you can create a PullPoint and create a Subscription for it inside the same service unit.
In addition to the deployment of service units, you can also create pull points or subscriptions dynamically from inside the JBI bus by using a simple API.
To create a subscription for a given JBI endpoint, you can use the following code:
QName service = ...; String endpoint = ...; String topic = ...; NotificationBroker wsnBroker = new NotificationBroker(getContext()); EndpointReferenceType consumer = new EndpointReferenceType(); consumer.setAddress(new AttributedURIType()); consumer.getAddress().setValue(service.getNamespaceURI() + "/" + service.getLocalPart() + "/" + endpoint); wsnBroker.subscribe(consumer, topic);
To publish a message on a given topic:
String topic = ...; NotificationBroker wsnBroker = new NotificationBroker(getContext()); wsnBroker.notify(topic, message);
where message is a DOM element.
You can also create pull points and subscriptions for them:
CreatePullPoint wsnCreatePullPoint = new CreatePullPoint(getContext()); PullPoint pullPoint = wsnCreatePullPoint.createPullPoint(); NotificationBroker wsnBroker = new NotificationBroker(getContext()); wsnBroker.subscribe(pullPoint.getEndpoint(), topic);
Later, you can pull notifications from this pull point:
List<NotificationMessageHolderType> msgs = pullPoint.getMessages(0);
If you want to use WS-Notification ouside the JBI world, you will need to be able to receive incoming requests or send notifications to the external services. This must be done through by using Binding Components, either using HTTP or JMS.
To expose the NotificationBroker and CreatePullPoint services using HTTP/SOAP, you can deploy the following configuration file to servicemix-http:
<beans xmlns:http="http://servicemix.apache.org/http/1.0" xmlns:wsn="http://servicemix.org/wsnotification"> <http:endpoint service="wsn:NotificationBroker" endpoint="http-binding" targetService="wsn:NotificationBroker" targetEndpoint="Broker" role="consumer" locationURI="http://localhost:8192/Broker/" defaultMep="http://www.w3.org/2004/08/wsdl/in-out" soap="true"/> <http:endpoint service="wsn:CreatePullPoint" endpoint="http-binding2" targetService="wsn:CreatePullPoint" targetEndpoint="Broker" role="consumer" locationURI="http://localhost:8192/CreatePullPoint/" defaultMep="http://www.w3.org/2004/08/wsdl/in-out" soap="true"/> </beans>
If you use a single static configuration file for ServiceMix, you can easily leverage this component to create subscription, pull-points and publish messages.
xmlns:sm="http://servicemix.apache.org/config/1.0" xmlns:wsn="http://servicemix.apache.org/wsn/1.0" xmlns:test="http://servicemix.org/test" <sm:activationSpec id="receiver" service="test:service" endpoint="endpoint"> <sm:component> <bean class="org.apache.servicemix.tck.ReceiverComponent" /> </sm:component> </sm:activationSpec> <sm:activationSpec> <sm:component> <wsn:component> <wsn:requests> <wsn:subscribe consumer="http://servicemix.org/test/service/endpoint" topic="myTopic" /> </wsn:requests> </wsn:component> </sm:component> </sm:activationSpec> <sm:activationSpec service="test:publisher" endpoint="endpoint"> <sm:component> <wsn:publisher topic="myTopic" /> </sm:component> </sm:activationSpec>
The above code snippet creates a publisher proxy, a subscription and a subscriber.
The publisher proxy is a simple component that wraps incoming JBI exchanges into WS-Notification notify requests and send them to a notification broker on the given topic. This could also be written in plain spring style:
<sm:activationSpec service="test:publisher" endpoint="endpoint"> <sm:component> <bean class="org.apache.servicemix.wsn.spring.PublisherComponent"> <property name="topic" value="myTopic" /> </bean> </sm:component> </sm:activationSpec>
When the component is started, it registers itself as a publisher to the WS-Notification broker. To do so, it activates a JBI endpoint named subscription so it can handle demand based publishing. When this component receives an InOnly exchange, let's say <hello>world</hello>, it will wrap it in a request as shown here and send the request as an InOnly exchange to the NotifiationBroker. Note that, as this component activates two JBI endpoints, you need to explicitely target the endpoint specified in the activationSpec when sending a message.
The subscription is created inside a servicemix-wsn2005 component. You must fill the consumer and topic properties, where the consumer is the URI-encoded target JBI endpoint, which will be resolved to the first component activated. You could also use the plain spring syntax:
<sm:activationSpec> <sm:component> <bean class="org.apache.servicemix.wsn.spring.WSNSpringComponent"> <property name="requests"> <list> <bean class="org.apache.servicemix.wsn.spring.SubscribeFactoryBean"> <property name="consumer" value="http://servicemix.org/test/service/endpoint" /> <property name="topic" value="myTopic" /> </bean> </list> </property> </bean> </sm:component> </sm:activationSpec>
The following xml snippets are just examples of WS-Notification requests. You should refer to the specification for more informations.
<wsnt:Subscribe xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing"> <wsnt:ConsumerReference> <wsa:Address> endpoint:http://www.consumer.org/service/endpoint </wsa:Address> </wsnt:ConsumerReference> <wsnt:Filter> <!-- Optional Topic Express Filter --> <wsnt:TopicExpression Dialect="http://docs.oasis-open.org/wsn/t-1/TopicExpression/Simple"> myTopic </wsnt:TopicExpression> <!-- Optional Message Content Filter --> <wsnt:MessageContent Dialect="http://www.w3.org/TR/1999/REC-xpath-19991116"> //hello/@id=123 <wsnt:MessageContent> </wsnt:Filter> </wsnt:Subscribe>
This request will create a subscription on the myTopic topic and will send messages to the JBI endpoint identified by its URI. In this case, the endpoint: protocol is used to identify an endpoint on the JBI bus.
<wsnt:CreatePullPoint xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:sm="http://servicemix.apache.org/wsn2005/1.0"> <sm:address> http://www.consumer.org/service/endpoint </sm:address> <sm:name>myPullPoint</sm:name> </wsnt:CreatePullPoint>
Note that the <sm:address/> element is a ServiceMix extension that creates a PullPoint on a specific JBI endpoint ([namespace][sep][service][sep][endpoint], see URIs). This is very useful when you want to create a subscription for this endpoint at deployment time (see the previous paragraph).
The <sm:name/> element is a second ServiceMix extension that can be used to specify the name of the PullPoint. Such a name is used as JMS queue name, so it may be useful to specify it if you want to address a specific queue. If none is set, a queue name will be automatically generated (note that some JMS providers may require some administration tasks to be performed to create a JMS destination).
The Notify request is sent by a publisher to the NotificationBroker. This request contains a list of NotificationMessage, each one containing:
Below is an example of a such a request.
<wsnt:Notify xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"> <wsnt:NotificationMessage> <wsnt:Topic>myTopic</wsnt:Topic> <wsnt:Message> <hello>world</hello> </wsnt:Message> </wsnt:NotificationMessage> </wsnt:Notify>