JBoss Web Services allows communication over the JMS transport. The functionality comes from Apache CXF support for the SOAP over Java Message Service 1.0 specification, which is aimed at a set of standards for interoperable transport of SOAP messages over JMS.
On top of Apache CXF functionalities, the JBossWS integration allows users to deploy WS archives containing both JMS and HTTP endpoints the same way as they do for basic HTTP WS endpoints (in war archives). The webservices layer of WildFly takes care of looking for JMS enpdoints in the deployed archive and starts them delegating to the Apache CXF core similarly as with HTTP endpoints.
As per specification, the SOAP over JMS transport configuration is controlled by proper elements and attributes in the binding and service elements of the WSDL contract. So a JMS endpoint is usually developed using a contract-first approach.
The Apache CXF documentation covers all the details of the supported configurations. The minimum configuration implies:
- setting a proper JMS URI in the soap:address location 
- providing a JNDI connection factory name to be used for connecting to the queues 
- setting the transport binding 
Apache CXF takes care of setting up the JMS transport for endpoint implementations whose @WebService annotation points to a port declared for JMS transport as explained above.
|JBossWS currently supports POJO endpoints only for JMS transport use. The endpoint classes can be deployed as part of jar or war archives.
The web.xml descriptor in war archives doesn't need any entry for JMS endpoints.
In this example we create a simple endpoint relying on SOAP over JMS and deploy it as part of a jar archive.
The endpoint is created using wsconsume tool from a WSDL contract such as:
|The HelloWorldImplPort here is meant for using the testQueue that has to be created before deploying the endpoint.|
At the time of writing, java:/ConnectionFactory is the default connection factory JNDI location.
For allowing remote JNDI lookup of the connection factory, a specific service (HelloWorldService) for remote clients is added to the WSDL. The java:jms/RemoteConnectionFactory is the JNDI location of the same connection factory mentioned above, except it's exposed for remote lookup. The soapjms:jndiInitialContextFactory and soap:jmsjndiURL complete the remote connection configuration: they depends on the actual WildFly container the service is running on and specify the initial context factory class to use and the JNDI registry address.
|Have a look at the application server domain for finding out the configured connection factory JNDI locations.|
The endpoint implementation is a basic JAX-WS POJO using @WebService annotation to refer to the consumed contract:
|The endpoint implementation references the HelloWorldServiceLocal wsdl service, so that the local JNDI connection factory location is used for starting the endpoint on server side.|
That's pretty much all. We just need to package the generated service endpoint interface, the endpoint implementation and the WSDL file in a jar archive and deploy it:
|A dependency on org.apache.activemq.artemis module needs to be added in MANIFEST.MF when deploying to WildFly.|
A JAX-WS client can interact with the JMS endpoint the usual way:
|The WSDL location URL needs to be retrieved in a custom way, depending on the client application. Given the endpoint is JMS only, there's no automatically published WSDL contract.|
in order for performing the remote invocation (which internally goes through remote JNDI lookup of the connection factory), the calling user credentials need to be set into the Apache CXF JMSConduit:
|Have a look at the WildFly domain and messaging configuration for finding out the actual security requirements. At the time of writing, a user with guest role is required and that's internally checked using the other security domain.|
Of course once the endpoint is exposed over JMS transport, any plain JMS client can also be used to send messages to the webservice endpoint. You can have a look at the SOAP over JMS spec details and code the client similarly to
In this example we create a deployment containing an endpoint that serves over both HTTP and JMS transports.
We from a WSDL contract such as below (please note we've two binding / portType for the same service):
The same considerations of the previous example regarding the JMS queue and JNDI connection factory still apply.
Here we can implement the endpoint in multiple ways, either with a common implementation class that's extended by the JMS and HTTP ones, or keep the two implementation classes independent and just have them implement the same service endpoint interface:
Both classes are packaged together the service endpoint interface and the WSDL file in a war archive:
A trivial web.xml descriptor is also included to trigger the HTTP endpoint publish:
|Here too the MANIFEST.MF needs to declare a dependency on org.apache.activemq.artemis module when deploying to WildFly.|
Finally, the JAX-WS client can ineract with both JMS and HTTP endpoints as usual:
An alternative to deploying an archive containing JMS endpoints is in starting them directly using the JAX-WS Endpoint.publish(..) API.
That's as easy as doing:
where HelloWorldImpl is a POJO endpoint implementation referencing a JMS port in a given WSDL contract, as explained in the previous examples.
The main difference among the deployment approach is in the direct control and responsibility over the endpoint lifecycle (start/publish and stop).