Bus bus = BusFactory.newInstance().createBus();
All JAX-WS functionalities provided by JBossWS on top of JBoss Application Server are currently served through a proper integration of the JBoss Web Services stack with most of the Apache CXF project modules.
Apache CXF is an open source services framework. It allows building and developing services using frontend programming APIs (including JAX-WS), with services speaking a variety of protocols such as SOAP and XML/HTTP over a variety of transports such as HTTP and JMS.
The integration layer (JBossWS-CXF in short hereafter) is mainly meant for:
allowing using standard webservices APIs (including JAX-WS) on JBoss Application Server; this is performed internally leveraging Apache CXF without requiring the user to deal with it;
allowing using Apache CXF advanced features (including WS-*) on top of JBoss Application server without requiring the user to deal with / setup / care about the required integration steps for running in such a container.
In order for achieving the goals above, the JBossWS-CXF integration supports the JBoss endpoint deployment and comes with many internal customizations on top of Apache CXF.
In the next sections a list of technical suggestions and notes on the integration is provided; please also refer to the Apache CXF official documentation for in-depth details on the CXF architecture.
Most of the Apache CXF features are configurable using the org.apache.cxf.Bus class. While for basic JAX-WS usage the user might never need to explicitly deal with Bus, using Apache CXF specific features generally requires getting a handle to a org.apache.cxf.Bus instance. This can happen on client side as well as in a ws endpoint or handler business code.
New Bus instances are produced by the currently configured org.apache.cxf.BusFactory implementation the following way:
Bus bus = BusFactory.newInstance().createBus();
The algorithm for selecting the actual implementation of BusFactory to be used leverages the Service API, basically looking for optional configurations in META-INF/services/... location using the current thread context classloader. JBossWS-CXF integration comes with his own implementation of BusFactory, org.jboss.wsf.stack.cxf.client.configuration.JBossWSBusFactory, that allows for automatic detection of Spring availability as well as seamless setup of JBossWS customizations on top of Apache CXF. So, assuming the JBossWS-CXF libraries are available in the current thread context classloader, the JBossWSBusFactory is automatically retrieved by the BusFactory.newInstance() call above.
JBossWS users willing to explicitely use functionalities of org.apache.cxf.bus.spring.SpringBusFactory or org.apache.cxf.bus.CXFBusFactory, get the same API with JBossWS additions through JBossWSBusFactory:
String myConfigFile = ... Bus bus = new JBossWSBusFactory().createBus(myConfigFile);
Map<Class, Object> myExtensions = new HashMap<Class, Object>(); myExtensions.put(...); Bus bus = new JBossWSBusFactory().createBus(myExtensions);
Apache CXF keeps reference to a global default Bus instance as well as to a thread default bus for each thread. That is performed through static members in org.apache.cxf.BusFactory, which also comes with the following methods in the public API:
public static synchronized Bus getDefaultBus() public static synchronized Bus getDefaultBus(boolean createIfNeeded) public static synchronized void setDefaultBus(Bus bus) public static Bus getThreadDefaultBus() public static Bus getThreadDefaultBus(boolean createIfNeeded) public static void setThreadDefaultBus(Bus bus)
Please note that the default behaviour of getDefaultBus() / getDefaultBus(true) / getThreadDefaultBus() / getThreadDefaultBus(true) is to create a new Bus instance if that's not set yet. Moreover getThreadDefaultBus() and getThreadDefaultBus(true) first fallback to retrieving the configured global default bus before actually trying creating a new instance (and the created new instance is set as global default bus if that was not there set yet).
The drawback of this mechanism (which is basically fine in JSE environment) is that when running in a JBoss AS container you need to be careful in order not to (mis)use a bus over multiple applications (assuming the Apache CXF classes are loaded by the same classloader, which is currently the case with AS6 and 7).
Here is a list of general suggestions to avoid problems when running in-container:
forget about the global default bus; you don't need that, so don't do getDefaultBus() / getDefaultBus(true) / setDefaultBus() in your code;
avoid getThreadDefaultBus() / getThreadDefaultBus(true) unless you already know for sure the default bus is already set;
keep in mind thread pooling whenever you customize a thread default bus instance (for instance adding bus scope interceptors, ...), as that thread and bus might be later reused; so either shutdown the bus when you're done or explicitly remove it from the BusFactory thread association.
Finally, remember that each time you explictly create a new Bus instance (factory.createBus()) that is set as thread default bus and global default bus if those are not set yet. The JAXWS Provider implementation also creates Bus instances internally, in particular the JBossWS version of JAXWS Provider makes sure the default bus is never internally used and instead a new Bus is created if required.
The JBossWS-CXF server side integration takes care of internally creating proper Apache CXF structures (including a Bus instance, of course) for the ws endpoint deployment.
While JBossWS sets sensible defaults for most of the Apache CXF configuration options on server side, users might want to fine tune the Bus instance that's created for their deployments.
The jboss-webservices.xml descriptor can be used to provide property values.
<webservices xmlns="http://www.jboss.com/xml/ns/javaee" version="1.2"> ... <property> <name>...</name> <value>...</value> </property> ... </webservices>
JBossWS-CXF integration comes with a set of allowed property names to control Apache CXF internals. The main advantage of the property based approach is that it does not require Spring libraries.
Apache CXF uses WorkQueue instances for dealing with some operations (e.g. @Oneway requests processing). A WorkQueueManager is installed in the Bus as an extension and allows for adding / removing queues as well as controlling the existing ones.
On server side, queues can be provided through Spring based Bus declaration or by using the cxf.queue.<queue-name>.* properties in jboss-webservices.xml (e.g. cxf.queue.default.maxQueueSize for controlling the max queue size of the default workqueue). At deployment time, the JBossWS integration can add new instances of AutomaticWorkQueueImpl to the currently configured WorkQueueManager; the properties below are used to fill in parameter into the AutomaticWorkQueueImpl constructor:
Property |
Default value |
cxf.queue.<queue-name>.maxQueueSize |
256 |
cxf.queue.<queue-name>.initialThreads |
0 |
cxf.queue.<queue-name>.highWaterMark |
25 |
cxf.queue.<queue-name>.lowWaterMark |
5 |
cxf.queue.<queue-name>.dequeueTimeout |
120000 |
The Apache CXF policy engine supports different strategies to deal with policy alternatives. JBossWS-CXF integration currently defaults to the MaximalAlternativeSelector, but still allows for setting different selector implementation using the cxf.policy.alternativeSelector property in jboss-webservices.xml.
It is possible to customize the JBossWS and CXF integration by incorporating the CXF configuration file to the endpoint deployment archive. In order for that to be possible, JBossWS-CXF requires Spring to be installed in the application server. The Spring Framework libraries installation can be performed using the JBossWS-CXF installation or by manually populating the org.springframework.spring module that's in JBoss AS 7 and which the other webservices modules already have an optional dependency on.
The convention is the following:
file name must be jbossws-cxf.xml
for POJO deployments it is located in WEB-INF directory
for EJB3 deployments it is located in META-INF directory
Providing custom CXF configuration to the endpoint deployment is useful in cases when users want to use features that are not part of standard JAX-WS specification (CXF specific) and that can't be setup in the application classes' code. An example are some advanced WS-RM customizations.