[[Apache_CXF_integration]] = Apache CXF integration [[jbossws-integration-layer-with-apache-cxf]] == JBossWS integration layer with Apache CXF All JAX-WS functionalities provided by JBossWS on top of WildFly are currently served through a proper integration of the JBoss Web Services stack with most of the http://cxf.apache.org/[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 WildFly; 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 WildFly 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 ws endpoint deployment mechanism 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 http://cxf.apache.org/docs/index.html[Apache CXF official documentation] for in-depth details on the CXF architecture. [[building-ws-applications-the-jboss-way]] == Building WS applications the JBoss way The Apache CXF client and endpoint configuration as explained in the http://cxf.apache.org/docs/index.html[Apache CXF official user guide] is heavily based on Spring. Apache CXF basically parses Spring `cxf.xml` descriptors; those may contain any basic bean plus specific ws client and endpoint beans which CXF has custom parsers for. Apache CXF can be used to deploy webservice endpoints on any servlet container by including its libraries in the deployment; in such a scenario Spring basically serves as a convenient configuration option, given direct Apache CXF API usage won't be very handy. Similar reasoning applies on client side, where a Spring based descriptor offers a shortcut for setting up Apache CXF internals. This said, nowadays almost any Apache CXF functionality can be configured and used through direct API usage, without Spring. As a consequence of that and given the considerations in the sections below, the JBossWS integration with Apache CXF does not rely on Spring descriptors. [[portable-applications]] === Portable applications WildFly is much more then a servlet container; it actually provides users with a fully compliant target platform for Java EE applications. Generally speaking, _users are encouraged to write portable applications_ by relying only on _JAX-WS specification_ whenever possible. That would by the way ensure easy migrations to and from other compliant platforms. Being a Java EE container, WildFly already comes with a JAX-WS compliant implementation, which is basically Apache CXF plus the JBossWS-CXF integration layer. So users just need to write their JAX-WS application; _no need for embedding any Apache CXF or any ws related dependency library in user deployments_. Please refer to the <> section of the documentation for getting started. WS-* usage (including WS-Security, WS-Addressing, WS-ReliableMessaging, ...) should also be configured in the most portable way; that is by _relying on proper WS-Policy assertions_ on the endpoint WSDL contracts, so that client and endpoint configuration is basically a matter of setting few ws context properties. The WS-* related sections of this documentation cover all the details on configuring applications making use of WS-* through policies. As a consequence of the reasoning above, the JBossWS-CXF integration is currently built directly on the Apache CXF API and aims at allowing users to configure webservice clients and endpoints _without Spring descriptors_. [[direct-apache-cxf-api-usage]] === Direct Apache CXF API usage Whenever users can't really meet their application requirements with JAX-WS plus WS-Policy, it is of course still possible to rely on direct Apache CXF API usage (given that's included in the AS), loosing the Java EE portability of the application. That could be the case of a user needing specific Apache CXF functionalities, or having to consume WS-* enabled endpoints advertised through legacy wsdl contracts without WS-Policy assertions. On server side, direct Apache CXF API usage might not be always possible or end up being not very easy. For this reason, the JBossWS integration comes with a convenient alternative through customization options in the `jboss-webservices.xml` descriptor described below on this page. Properties can be declared in `jboss-webservices.xml` to control Apache CXF internals like _interceptors_, _features_, etc. [[bus-usage]] == Bus usage [[creating-a-bus-instance]] === Creating a Bus instance 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: [source, java] ---- 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 its own implementation of `BusFactory`, `org.jboss.wsf.stack.cxf.client.configuration.JBossWSBusFactory`, that allows for 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 explicitly use functionalities of `org.apache.cxf.bus.CXFBusFactory` _,_ get the same API with JBossWS additions through `JBossWSBusFactory`: [source, java] ---- Map myExtensions = new HashMap(); myExtensions.put(...); Bus bus = new JBossWSBusFactory().createBus(myExtensions); ---- [[using-existing-bus-instances]] === Using existing Bus instances 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: [source, java] ---- 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 set there yet). The drawback of this mechanism (which is basically fine in JSE environment) is that when running in WildFly 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 WildFly). 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 (more details on this in the next paragraph). [[bus-selection-strategies-for-jaxws-clients]] === Bus selection strategies for JAXWS clients JAXWS clients require an Apache CXF Bus to be available; the client is registered within the Bus and the Bus affects the client behavior (e.g. through the configured CXF interceptors). The way a bus is internally selected for serving a given JAXWS client is very important, especially for in-container clients; for this reason, JBossWS users can choose the preferred Bus selection strategy. The strategy is enforced in the `javax.xml.ws.spi.Provider` implementation from the JBossWS integration, being that called whenever a JAXWS `Service` (client) is requested. [[thread-bus-strategy-thread_bus]] ==== Thread bus strategy (THREAD_BUS) Each time the vanilla JAXWS api is used to create a Bus, the JBossWS-CXF integration will automatically make sure a Bus is currently associated to the current thread in the BusFactory. If that's not the case, a new Bus is created and linked to the current thread (to prevent the user from relying on the default Bus). The Apache CXF engine will then create the client using the current thread Bus. This is the default strategy, and the most straightforward one in Java SE environments; it lets users automatically reuse a previously created Bus instance and allows using customized Bus that can possibly be created and associated to the thread before building up a JAXWS client. The drawback of the strategy is that the link between the Bus instance and the thread needs to be eventually cleaned up (when not needed anymore). This is really evident in a Java EE environment (hence when running in-container), as threads from pools (e.g. serving web requests) are re-used. When relying on this strategy, the safest approach to be sure of cleaning up the link is to surround the JAXWS client with a `try/finally` block as below: [source, java] ---- try { Service service = Service.create(wsdlURL, serviceQName); MyEndpoint port = service.getPort(MyEndpoint.class); //... } finally { BusFactory.setThreadDefaultBus(null); // OR (if you don't need the bus and the client anymore) Bus bus = BusFactory.getThreadDefaultBus(false); bus.shutdown(true); } ---- [[new-bus-strategy-new_bus]] ==== New bus strategy (NEW_BUS) Another strategy is to have the JAXWS Provider from the JBossWS integration create a new Bus each time a JAXWS client is built. The main benefit of this approach is that a fresh bus won't rely on any formerly cached information (e.g. cached WSDL / schemas) which might have changed after the previous client creation. The main drawback is of course worse performance as the Bus creation takes time. If there's a bus already associated to the current thread before the JAXWS client creation, that is automatically restored when returning control to the user; in other words, the newly created bus will be used only for the created JAXWS client but won't stay associated to the current thread at the end of the process. Similarly, if the thread was not associated to any bus before the client creation, no bus will be associated to the thread at the end of the client creation. [[thread-context-classloader-bus-strategy-tccl_bus]] ==== Thread context classloader bus strategy (TCCL_BUS) The last strategy is to have the bus created for serving the client be associated to the current thread context classloader (TCCL). That basically means the same Bus instance is shared by JAXWS clients running when the same TCCL is set. This is particularly interesting as each web application deployment usually has its own context classloader, so this strategy is possibly a way to keep the number of created Bus instances bound to the application number in WildFly container. If there's a bus already associated to the current thread before the JAXWS client creation, that is automatically restored when returning control to the user; in other words, the bus corresponding to the current thread context classloader will be used only for the created JAXWS client but won't stay associated to the current thread at the end of the process. If the thread was not associated to any bus before the client creation, a new bus will be created (and later user for any other client built with this strategy and the same TCCL in place); no bus will be associated to the thread at the end of the client creation. [[strategy-configuration]] ==== Strategy configuration Users can request a given Bus selection strategy to be used for the client being built by specifying one of the following JBossWS features (which extend `javax` `.` `xml` `.` `ws` `.` `WebServiceFeature`): [cols=",",options="header"] |============================================================== |Feature |Strategy |org.jboss.wsf.stack.cxf.client.UseThreadBusFeature |THREAD_BUS |org.jboss.wsf.stack.cxf.client.UseNewBusFeature |NEW_BUS |org.jboss.wsf.stack.cxf.client.UseTCCLBusFeature |TCCL_BUS |============================================================== The feature is specified as follows: [source, java] ---- Service service = Service.create(wsdlURL, serviceQName, new UseThreadBusFeature()); ---- If no feature is explicitly specified, the system default strategy is used, which can be modified through the `org.jboss.ws.cxf.jaxws-client.bus.strategy` system property when starting the JVM. The valid values for the property are `THREAD_BUS`, `NEW_BUS` and `TCCL_BUS`. The default is `THREAD_BUS`. [[server-side-integration-customization]] == Server Side Integration Customization The JBossWS-CXF server side integration takes care of internally creating proper Apache CXF structures (including a `Bus` instance, of course) for the provided ws deployment. Should the deployment include multiple endpoints, those would all live within the same Apache CXF Bus, which would of course be completely separated by the other deployments' bus instances. 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 deployment; a `jboss-webservices.xml` descriptor can be used for deployment level customizations. [[deployment-descriptor-properties]] === Deployment descriptor properties The `jboss-webservices.xml` descriptor can be used to <>. [source,xml] ---- ... ... ... ... ---- JBossWS-CXF integration comes with a set of allowed property names to control Apache CXF internals. [[workqueue-configuration]] ==== WorkQueue configuration Apache CXF uses WorkQueue instances for dealing with some operations (e.g. @Oneway requests processing). A http://cxf.apache.org/javadoc/latest-2.5.x/org/apache/cxf/workqueue/WorkQueueManager.html[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 by using the `cxf.queue..*` 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 http://cxf.apache.org/javadoc/latest-2.5.x/org/apache/cxf/workqueue/AutomaticWorkQueueImpl.html[AutomaticWorkQueueImpl] to the currently configured WorkQueueManager; the properties below are used to fill in parameter into the http://cxf.apache.org/javadoc/latest-2.5.x/org/apache/cxf/workqueue/AutomaticWorkQueueImpl.html#AutomaticWorkQueueImpl(int,%20int,%20int,%20int,%20long,%20java.lang.String)[AutomaticWorkQueueImpl constructor]: [cols=",",options="header"] |============================================= |Property |Default value |cxf.queue..maxQueueSize |256 |cxf.queue..initialThreads |0 |cxf.queue..highWaterMark |25 |cxf.queue..lowWaterMark |5 |cxf.queue..dequeueTimeout |120000 |============================================= [[policy-alternative-selector]] ==== Policy alternative selector The Apache CXF policy engine supports different strategies to deal with policy alternatives. JBossWS-CXF integration currently defaults to the http://cxf.apache.org/javadoc/latest-2.5.x/org/apache/cxf/ws/policy/selector/MaximalAlternativeSelector.html[MaximalAlternativeSelector], but still allows for setting different selector implementation using the `cxf.policy.alternativeSelector` property in `jboss-webservices.xml`. [[mbean-management]] ==== MBean management Apache CXF allows managing its MBean objects that are installed into the WildFly MBean server. The feature is enabled on a deployment basis through the `cxf.management.enabled` property in `jboss-webservices.xml`. The `cxf.management.installResponseTimeInterceptors` property can also be used to control installation of CXF response time interceptors, which are added by default when enabling MBean management, but might not be desired in some cases. Here is an example: [source,xml] ---- cxf.management.enabled true cxf.management.installResponseTimeInterceptors false ---- [[schema-validation]] ==== Schema validation Schema validation of exchanged messages can also be enabled in `jboss-webservices.xml`. Further details available <>. [[interceptors]] ==== Interceptors The `jboss-webservices.xml` descriptor also allows specifying the `cxf.interceptors.in` and `cxf.interceptors.out` properties; those allows declaring interceptors to be attached to the Bus instance that's created for serving the deployment. [source,xml] ----   cxf.interceptors.in org.jboss.test.ws.jaxws.cxf.interceptors.BusInterceptor cxf.interceptors.out org.jboss.test.ws.jaxws.cxf.interceptors.BusCounterInterceptor ---- [[features]] ==== Features The `jboss-webservices.xml` descriptor also allows specifying the `cxf.features` property; that allows declaring features to be attached to any endpoint belonging to the Bus instance that's created for serving the deployment. [source,xml] ----   cxf.features org.apache.cxf.feature.FastInfosetFeature ---- [[ws-discovery-enablement]] ==== WS-Discovery enablement WS-Discovery support can be turned on in `jboss-webservices` for the current deployment. Further details available <>. [[apache-cxf-interceptors]] == Apache CXF interceptors Apache CXF supports declaring interceptors using one of the following approaches: * Annotation usage on endpoint classes ( `@org.apache.cxf.interceptor.InInterceptor`, `@org.apache.cxf.interceptor.OutInterceptor`) * Direct API usage on client side (through the `org.apache.cxf.interceptor.InterceptorProvider` interface) * Spring descriptor usage ( _cxf.xml_) As the Spring descriptor usage is not supported, the JBossWS integration adds an additional descriptor based approach to avoid requiring modifications to the actual client/endpoint code. Users can declare interceptors within <> by specifying a list of interceptor class names for the `cxf.interceptors.in` and `cxf.interceptors.out` properties. [source,xml] ---- org.jboss.test.ws.jaxws.cxf.interceptors.EndpointImpl cxf.interceptors.in org.jboss.test.ws.jaxws.cxf.interceptors.EndpointInterceptor,org.jboss.test.ws.jaxws.cxf.interceptors.FooInterceptor cxf.interceptors.out org.jboss.test.ws.jaxws.cxf.interceptors.EndpointCounterInterceptor ---- A new instance of each specified interceptor class will be added to the client or endpoint the configuration is assigned to. The interceptor classes must have a no-argument constructor. [[apache-cxf-features]] == Apache CXF features Apache CXF supports declaring features using one of the following approaches: * Annotation usage on endpoint classes ( `@org.apache.cxf.feature.Features`) * Direct API usage on client side (through extensions of the `org.apache.cxf.feature.AbstractFeature` class) * Spring descriptor usage ( _cxf.xml_) As the Spring descriptor usage is not supported, the JBossWS integration adds an additional descriptor based approach to avoid requiring modifications to the actual client/endpoint code. Users can declare features within <> by specifying a list of feature class names for the `cxf.features` property. [source,xml] ---- Custom FI Config cxf.features org.apache.cxf.feature.FastInfosetFeature ---- A new instance of each specified feature class will be added to the client or endpoint the configuration is assigned to. The feature classes must have a no-argument constructor. [[properties-driven-bean-creation]] == Properties driven bean creation Sections above explain how to declare CXF interceptors and features through properties either in a client/endpoint predefined configuration or in a `jboss-webservices.xml` descriptor. By getting the feature/interceptor class name only specified, the container simply tries to create a bean instance using the class default constructor. This sets a limitation on the feature/interceptor configuration, unless custom extensions of vanilla CXF classes are provided, with the default constructor setting properties before eventually using the super constructor. To cope with this issue, JBossWS integration comes with a mechanism for configuring simple bean hierarchies when building them up from properties. Properties can have bean reference values, that is strings starting with `##`. Property reference keys are used to specify the bean class name and the value for for each attribute. So for instance the following properties: [cols=",",options="header"] |========================== |Key |Value |cxf.features |##foo, ##bar |##foo |org.jboss.Foo |##foo.par |34 |##bar |org.jboss.Bar |##bar.color |blue |========================== would result into the stack installing two feature instances, the same that would have been created by [source, java] ---- import org.Bar; import org.Foo;   ...   Foo foo = new Foo(); foo.setPar(34); Bar bar = new Bar(); bar.setColor("blue"); ---- The mechanism assumes that the classes are valid beans with proper getter and setter methods; value objects are cast to the correct primitive type by inspecting the class definition. Nested beans can of course be configured. [[httpconduit-configuration]] == HTTPConduit configuration HTTP transport setup in Apache CXF is achieved through `org.apache.cxf.transport.http.HTTPConduit` http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html[configurations]. When running on top of the JBossWS integration, conduits can be programmatically modified using the Apache CXF API as follows: [source, java] ---- import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.transport.http.HTTPConduit; import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;   //set chunking threshold before using a JAX-WS port client ... HTTPConduit conduit = (HTTPConduit)ClientProxy.getClient(port).getConduit(); HTTPClientPolicy client = conduit.getClient();   client.setChunkingThreshold(8192); ... ---- Users can also control the default values for the most common HTTPConduit parameters by setting specific system properties; the provided values will override Apache CXF defaut values. [cols=",",options="header"] |======================================================================= |Property |Description |cxf.client.allowChunking |A boolean to tell Apache CXF whether to allow send messages using chunking. |cxf.client.chunkingThreshold |An integer value to tell Apache CXF the threshold at which switching from non-chunking to chunking mode. |cxf.client.connectionTimeout |A long value to tell Apache CXF how many milliseconds to set the connection timeout to |cxf.client.receiveTimeout |A long value to tell Apache CXF how many milliseconds to set the receive timeout to |cxf.client.connection |A string to tell Apache CXF to use Keep-Alive or close connection type |cxf.tls-client.disableCNCheck |A boolean to tell Apache CXF whether disabling CN host name check or not |======================================================================= The vanilla Apache CXF defaults apply when the system properties above are not set.