Home > Apache Tuscany Docs 2.x > Index > SCA Java Extensions Guide > SCA Java binding.jms |
Apache Tuscany Docs 2.x > Index > SCA Java Extensions Guide > SCA Java binding.jms | Tuscany Home | User List | Dev List | Issue Tracker |
Apache Tuscany Docs 2.x
SCA Java binding.jms
<binding.jms>The Tuscany Java SCA runtime supports the Java Messaging Service using the <binding.jms> SCDL extension. New JMS based service endpoints can be provided using a <binding.jms> element within a SCA <service>, existing JMS queues can be accessed using a <binding.jms> element within a SCA <reference>. The JMS binding is one of the SCA extensions which is being formalized in the OASIS Open Composite Services Architecture with a published specifications document. Using the JMS bindingThe simplest way to use the JMS binding is to use the URI syntax to configure the binding, for example: <binding.jms uri="jms:RequestQueue"/>
This tells the binding to use a JMS destination named "RequestQueue", with all the other configuration options using default values. By default Tuscany will use a JMS connection factory named 'ConnectionFactory', this can be changed by using a query parameter in the URI, for example, to use a connection factory named 'myCF' can be done as follows: <binding.jms uri="jms:RequestQueue?connectionFactoryName=myCF"/>
When using a SCA reference for RPC style requests and no response destination is defined in the SCDL then a temporary replyTo queue will automatically be created and used. When using the JMS binding with SCA services the syntax can be simplified even further by letting the destination name default to the service name. For example, the following SCDL snippet creates a JMS service listening on a JMS destination named "MyService":
<service name="MyService">
<binding.jms />
</service>
Validation in the JMS BindingTuscany performs two types of validation of the JMS Binding specified in a composite file.
Validation rules are taken from the binding schema and the OSOA and OASIS specs:
Invalid JMS bindings usually result in a JMSBindingException with error message and specific context of the error. See the JMSBindingProcessor for a complete list of validation rules. Some ExamplesHelloWorldThe helloworld-jms sample demonstrates basic RPC style operations over JMS. The sample has one component exposing a JMS service on a queue name 'HelloWorldService' and another component which invokes the service by sending JMS messages to that queue. A temporary destination is used for the response messages. The .composite file for this is shown below, see the helloworld sample README for full details. <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://sample" xmlns:sample="http://sample" name="HelloWorld"> <component name="HelloWorldClient"> <implementation.java class="helloworld.HelloWorldClient"/> <reference name="helloWorldRef"> <binding.jms uri="jms:HelloWorldService"/> </reference> </component> <component name="HelloWorldServiceComponent"> <implementation.java class="helloworld.HelloWorldServiceImpl" /> <service name="HelloWorldService"> <binding.jms /> </service> </component> </composite> Operation SelectionOperation selection extensions allow you to choose how the JMS bindings determines which service operation to call based on the incoming MS message.
While you can specify the default operation selector there is no need to as in lieu of other operation selectors being specified this one it assumed to be in force. You can add new operation selectors by adding the appropriate model objects, processors and providers. Following operation selection the actual operation that is called may be further affected by operationProperties configuration. Wire FormatsWire format extensions allow you to choose how message data is expected to appear inside the JMS message as it flows across the wire.
While you can specify this wire format there is no need to as in lieu of other operation selectors being specified this one it assumed to be in force. You can add new wire formats by adding the appropriate model objects, processors and providers. Using SCA callbacks with the JMS bindingThe Tuscany JMS binding supports using SCA callbacks for creating asynchronous clients and services. This is done by using a <callback> element in the SCDL for the service or reference as shown in the following example. <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://sample" name="CallbacksComposite"> <component name="ClientComponent"> <implementation.java class="callbacks.OrderServiceClient" /> <reference name="orderService" target="ServiceComponent/OrderService"> <binding.jms uri="jms:OrderService"/> <callback> <binding.jms /> </callback> </reference> </component> <component name="ServiceComponent"> <implementation.java class="callbacks.OrderServiceImpl" /> <service name="OrderService"> <binding.jms /> <callback> <binding.jms /> </callback> </service> </component> </composite> When no destination is defined on the callback binding of a <reference> then a JMS temporary queue will be used. Setting JMS headers and user propertiesJMS headers and user properties can be set on JMS messages sent from Tuscany by using the <Headers> and <OperationProperties> elements of the JMS binding. The <Headers> element applies to all messages, the <OperationProperties> applies to individual operations and may override values set on the <Headers> element. An example of using these is shown in the following snippet of SCDL: <binding.jms uri="jms:ServiceQueue"> <headers JMSType="someTypeValue" /> <operationProperties name="op2"> <headers JMSType="op2SpecificTypeValue" /> </operationProperties> </binding.jms> A complete working example of using <Headers> and <OperationProperties> can be seen in the properties itest Using JMS message selectorsServices using the JMS binding to receive messages may only want a subset of the messages arriving on a queue or topic. This can be done by using the <SubscriptionHeaders> element which enables defining a JMS message selector to filter the messages that will be received. An example of using these is shown in the following snippet of SCDL: <binding.jms uri="jms:ServiceTopic" > <SubscriptionHeaders JMSSelector="JMSType = 'type1'"/> </binding.jms> A complete working example of using <SubscriptionHeaders> can be seen in the jms selectors itest . Using a definitions.xml file and the requestConnection/responseConnection attributesIt can be useful to define the details of the JMS resources separately from the SCA composite, to support this the SCA definitions.xml file can be used to define 'model' <binding.jms> elements which can then be referred to from the binding within the composite. For example, the following shows a definitions.xml file defining a JMS queue and connection factory which are then used by a JMS binding within a composite. The definitions.xml file: <definitions xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:itest="http://jms" targetNamespace="http://jms" > <binding.jms name="itest:TestService" > <destination name="MyServiceQueue" create="never"/> <connectionFactory name="MyConnectionFactory"/> </binding.jms> </definitions> and a binding which uses the definitions.xml binding: <binding.jms requestConnection="itest:TestService" />
A complete working example of using the requestConnection/responseConnection attributes can be seen in the jms definitions itest . Configuring JMS resourcesTuscany locates all JMS resources from JNDI so the environment where Tuscany is running needs to have JNDI and JMS correctly configured in order to use the Tuscany JMS binding. The following describes how to configure JMS in some common environments: Tuscany J2SE standalone environment with ActiveMQThe Tuscany standalone runtime can use an embedded Apache ActiveMQ message broker. To use ActiveMQ the application needs to include the JMS API and ActiveMQ jars in the classpath and include a jndi.properties file to configure the ActiveMQ resources in JNDI. An example of this can be seen in the Tuscany JMS itest which uses the ActiveMQ 4.1.1 release and this jndi.properties file. For more information on using ActiveMQ see the Apache ActiveMQ website and specifically this page for information about configuring JNDI resources. Apache TomcatTomcat does not include a JMS broker by default so you need to either embed one in each Tuscany application, install a broker into the tomcat installation, or use an external broker. Once that is done JNDI resources can be defined using the standard Tomcat facilities, see the Tomcat JNDI How-to. The Tuscany samples that use JMS and Tomcat demonstrate how to embed a JMS broker within the application by including ActiveMQ and its dependencies within the sample WAR, and using the webapp META-INF/context.xml file to define the JMS resources in JNDI. JEE application servers such as Apache Geronimo, WebSphere etcJEE Application servers such as Geronimo, WebSphere, WebLogic etc come with their own JMS broker that can be used by Tuscany. All the JMS resources used by a Tuscany application must be manually defined in the application server. Usually the application server has some sort of admin console where the resources can be defined using a web browser. The Tuscany helloworld JMS sample README describes the specific details of how to do this for some common application servers.
Using JEE resource referencesWhen running Tuscany in a JEE environment it can be useful to use JEE resource references to map local application resource names to global JNDI names. This can be done by using <resource-ref> elements in the application deployment descriptor. If a <resource-ref> exists for a JMS binding resource then Tuscany will use that instead of looking up the resource directly in the global JNDI. For example, adding the following definitions to the helloworld JMS sample web.xml will enable mapping the 'ConnectionFactory' and 'HelloWorldService' names used by the JMS binding into names for the actual resources used on the Application Server. This will normally occur when the application is dployed with the deploy tool asking what real resource names the resourecs should be mapped to. <resource-ref> <res-ref-name>ConnectionFactory</res-ref-name> <res-type>javax.jms.ConnectionFactory</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref> <resource-ref> <res-ref-name>HelloWorldService</res-ref-name> <res-type>javax.jms.Queue</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref> Using an external JMS brokerWhen the Tuscany environment does not include a JMS broker then an external broker may be used by specifying the initialContextFactory and jndiURL attributes on the binding.jms element. Any JMS 1.1 compatible broker should work such as Apache ActiveMQ or any other proprietary broker. The Tuscany application classpath will need to include jars for the initial context factory and all of its dependencies. An example of using the Tuscany JMS binding with an external ActiveMQ broker is as follows: <binding.jms initialContextFactory="org.apache.activemq.jndi.ActiveMQInitialContextFactory" jndiURL="tcp://localhost:61616"> <destination name="DestQueueA"/> </binding.jms> Using the WebSphere client for JMSThe Tuscany JMS binding now (post Tuscany SCA 1.2) works the WebSphere client for JMS which enables Tuscany applications running outside of WebSphere to use JMS resources defined within WebSphere. You need to include the JMS client jars in the Tuscany classpath and ensure that the JMS connection factory has the "endpoint providers" field configured in WebSphere. See this email thread for more information. JMS Message types and message body formatThe SCA JMS specification only defines how to use JMS TextMessages which contain XML in the message body, however it is a common requirement to use alternative message types and body formats. Currently Tuscany defines an additional "messageProcessor" attribute on the binding.jms element to support additional message types and payload formats. For the time being this should be considered an interim solution which will be changed in future Tuscany releases. The messageProcessor attribute value may be "XMLTextMessage", "TextMessage", "ObjectMessage", or the name of a Java class that implements the org.apache.tuscany.sca.binding.jms.provider.JMSMessageProcessor interface. For example: <reference name="serviceA" promote="HelloWorldClient/serviceA"> <binding.jms messageProcessor="my.TestMessageProcessor" /> </reference> For a complete example of using the messageProcessor attribute see the MessageProcessorTestCase itest. Using policy to control the JMS bindingThe JMS binding is aware of the following policy implementations.
Intents and policy sets can be constructed to control the application of these policies. The following intents are defined by default
New intents and policy sets can be designed are required to provide the level of control you need over your application. Intent: priorityThe priority intent provides a coarse grained approach to setting message priority. For example, <reference name="serviceA" promote="HelloWorldClient/serviceA" requires="priotiry.meduim"> <binding.jms messageProcessor="my.TestMessageProcessor" /> </reference> The values "priority.high", "priority.medium", "priority.low" are supported. It is the responsibility of the user to define a policy set to support these intents. The following policy set could be used to support these priority values. <policySet name="JMSPolicySet1" provides="priority" appliesTo="sca:binding.jms"> <intentMap provides="priority" default="medium"> <qualifier name="high"> <tuscany:jmsHeader JMSPriority="9"/> </qualifier> <qualifier name="medium"> <tuscany:jmsHeader JMSPriority="4"/> </qualifier> <qualifier name="low"> <tuscany:jmsHeader JMSPriority="0"/> </qualifier> </intentMap> </policySet> Intent: deliveryModeThe deliveryMode intent provides s simple way of specifying whether a message should be delivered persistently or non-persistently. For example, <reference name="serviceA" promote="HelloWorldClient/serviceA" requires="deliveryMode.persistent"> <binding.jms messageProcessor="my.TestMessageProcessor" /> </reference> The values "deliveryMode.persistent" and "deliveryMode.nonPersistent" are supported. It is the responsibility of the user to define a policy set to support these intents. The following policy set could be used to support these delivery mode values. <policySet name="JMSPolicySet2" provides="deliveryMode" appliesTo="sca:binding.jms"> <intentMap provides="deliveryMode" default="nonPersistent"> <qualifier name="persistent"> <tuscany:jmsHeader JMSDeliveryMode="PERSISTENT"/> </qualifier> <qualifier name="nonPersistent"> <tuscany:jmsHeader JMSDeliveryMode="NON_PERSISTENT"/> </qualifier> </intentMap> </policySet> Other header valuesTBD JMS binding schemaThe complete JMS binding SCDL schema has the following format: <binding.jms correlationScheme="string"? initialContextFactory="xs:anyURI"? jndiURL="xs:anyURI"? requestConnection="QName"? responseConnection="QName"? operationProperties="QName"? ... > <destination name="xs:anyURI" type="string"? create="string"?> <property name="NMTOKEN" type="NMTOKEN">* </destination>? <connectionFactory name="xs:anyURI" create="string"?> <property name="NMTOKEN" type="NMTOKEN">* </connectionFactory>? <activationSpec name="xs:anyURI" create="string"?> <property name="NMTOKEN" type="NMTOKEN">* </activationSpec>? <response> <destination name="xs:anyURI" type="string"? create="string"?> <property name="NMTOKEN" type="NMTOKEN">* </destination>? <connectionFactory name="xs:anyURI" create="string"?> <property name="NMTOKEN" type="NMTOKEN">* </connectionFactory>? <activationSpec name="xs:anyURI" create="string"?> <property name="NMTOKEN" type="NMTOKEN">* </activationSpec>? </response>? <complexType name="SubscriptionHeaders"> <attribute name="JMSSelector" type="string"/> </complexType> <resourceAdapter name="NMTOKEN">? <property name="NMTOKEN" type="NMTOKEN">* </resourceAdapter>? <headers JMSType="string"? JMSCorrelationId="string"? JMSDeliveryMode="string"? JMSTimeToLive="int"? JMSPriority="string"?> <property name="NMTOKEN" type="NMTOKEN">* </headers>? <operationProperties name="string" nativeOperation="string"?> <headers JMSType="string"? JMSCorrelationId="string"? JMSDeliveryMode="string"? JMSTimeToLive="int"? JMSPriority="string"?> <property name="NMTOKEN" type="NMTOKEN">* </headers>? </operationProperties>* <opertionSelector.jmsdefault/>? | <opertionSelector.jmsUserProp propertyName="somePropertyName"/>? <wireFormat.jmsdefault sendFormat+"text|bytes"/>? | <wireFormat.jmsBytes/>? | <wireFormat.jmsBytesXML/>? | <wireFormat.jmsText/>? | <wireFormat.jmsTextXML/>? | <wireFormat.jmsObject/>? </binding.jms> See the JMS Binding Specification 1.0 for full details of each of these configuration options. Not all these elements are supported by Tuscany. Specifically, the <activationSpec> and <resourceAdapter> elements are not supported as Tuscany does not use JCA or MDBs for its JMS support. The create attribute on the destination element is not supported in most environments and all JMS resources (connection factories, queues and topics) need to be pre-configured. An exception to this is when using Apache ActiveMQ as the JMS broker then Tuscany may be able to dynamically create queue and topic resources. This is mainly only useful for unit testing and it is recommended that user applications are designed with the expectation that JMS resources need to be preconfigured. the "operationSelector" and "wireFormat" elements are declared in the tuscany namespace (http://tuscany.apache.org/xmlns/sca/1.0). The default operation selection and wire format behvaviour is defined in the JMS Binding Specification 1.0 but we have added a selection of other formats and selectors as alternatives. Implementation NotesThe JMS binding is the first binding where we have started to exploit the binding wire concept. This affects how the JMS binding is implemented. The addition of a binding wire to the infrastructure allows interceptors to be added that operate on message data in the context of the binding. This allows wire formats to be specified. This is important for bindings like JMS where the data format on the wire does not necessarily follow a well known specification. The default wire format in the Tuscany JMS binding is as described in the SCA JMS specification, i.e. a JMS text message containing XML. However JMS messages using any arbitrary format can be supported by constructing new wire format extensions. The following diagram shows an overview of how a reference JMS binding may be configured to talk to a service JMS binding using the Text XML wire format.
In the above diagram, An example of a composite file which results in this kind of configuration is as follows: <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://helloworld" xmlns:hw="http://helloworld" name="helloworld"> <component name="HelloWorldReferenceComponent"> <implementation.java class="org.apache.tuscany.sca.binding.jms.format.jmstextxml.helloworld.HelloWorldReferenceImpl" /> <reference name="helloWorldService1" > <binding.jms> <destination name="HelloWorldService1"/> <wireFormat.jmsTextXML/> </binding.jms> </reference> </component> <component name="HelloWorldServiceComponent1"> <implementation.java class="org.apache.tuscany.sca.binding.jms.format.jmstextxml.helloworld.HelloWorldServiceImpl" /> <service name="HelloWorldService"> <binding.jms> <destination name="HelloWorldService1"/> </binding.jms> </service> </component> </composite> Note that <wireFormat.jmsTextXML/> is explicitly specified on the reference binding. As this is the default wire format it can be omitted as is the case on the service binding. Of course Tuscany already has a databinding framework that is able to transform between datatypes generically. So think of the wire format functionality as performing binding specific transformations. The following diagram gives an overview of the difference between the databinding and wireformat transformations on the reference side:
The following diagram gives an overview of the difference between the databinding and wireformat transformations on the service side:
When looking at the code itself you will see the following structure:
binding-jms
The jms binding model
binding-jms-runtime
/org/apache/tuscany/sca/binding/jms/provider
The base JMS binding runtime implementation. Exploits the Tuscany provider pattern.
/org/apache/tuscany/sca/binding/jms/context
A structure that passes the binding context with the message and allows the wire format and operation selection interceptors to do binding specific things
/org/apache/tuscany/sca/binding/jms/transport
JMS transport processing implmented as an interceptor
/org/apache/tuscany/sca/binding/jms/headers
JMS header processing implmented as an interceptor
/org/apache/tuscany/sca/binding/jms/wireformat
JMS wire format interceptors
/org/apache/tuscany/sca/binding/jms/operationselector
JMS operation selector interceptors
binding-jms-policy
Some base JMS policy implementations
The providers can be replaced in order to change the way that the JMS binding is constructed.
|
Bookmark this on Delicious Digg this | Privacy Policy - Copyright © 2003-2010, The Apache Software Foundation, Licensed under ASL 2.0. |