How to develop CXF Web services with JBoss / WildFly
javax.* code to jakarta.xml.ws, deploy to a modern Apache CXF-powered WildFly runtime, configure production-grade timeouts, implement secure transport (HTTPS & WS-Security), and deploy seamlessly to Kubernetes/OpenShift environments.
For WildFly users, we recommend checking this article: SOAP Web services on WildFly made simple
WildFly 41.0.1.Final ships with JBossWS-CXF as its default, reference Apache CXF web services implementation. In this tutorial, we will show how to create a simple JAX-WS Web service endpoint, compile it using Jakarta EE 11 standards, and deploy and test it with a modern Java client.
Apache CXF is an open-source services framework that helps you build high-performance web services using standard programming APIs like JAX-WS (Jakarta XML Web Services) and JAX-RS (Jakarta RESTful Web Services). It supports SOAP, XML/HTTP, and various enterprise-grade WS-* standards, working efficiently over HTTP, JMS, or other custom transports.
Developing the Web Service (Jakarta EE 11)
To begin, create a new Maven Web Project using your favorite IDE (such as IntelliJ IDEA or Eclipse). Ensure your project targets Jakarta EE 11 by setting up your pom.xml to reference the Jakarta EE 11 APIs.
First, define the Service Endpoint Interface (SEI). We will use the standard annotations from the jakarta.jws and jakarta.xml.ws packages:
package com.sample;
import jakarta.jws.WebMethod;
import jakarta.jws.WebService;
@WebService
public interface Math {
@WebMethod
public long sum(long a, long b);
}
Next, implement the interface. The implementation class links back to the interface using the endpointInterface property within the @WebService annotation:
package com.sample;
import jakarta.jws.WebService;
@WebService(endpointInterface = "com.sample.Math", serviceName = "MathWS")
public class MathWS implements Math {
@Override
public long sum(long a, long b) {
System.out.println("Summing " + a + " + " + b);
return a + b;
}
}
Packaging and Deployment Descriptors
With Jakarta EE 11 and Servlet 6.0, deploying a SOAP endpoint to WildFly is simpler than ever. If you package your application as a .war file, WildFly automatically scans, registers, and publishes your annotated @WebService class—meaning a web.xml is completely optional! However, if you need to override the URL mappings or specify servlet rules, here is a modern Servlet 6.0-compliant web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<servlet>
<servlet-name>MathWS</servlet-name>
<servlet-class>com.sample.MathWS</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MathWS</servlet-name>
<url-pattern>/MathWS</url-pattern>
</servlet-mapping>
</web-app>
Modern Deployment Config vs. Legacy Spring XML
Legacy Note: In older JBoss AS 5 environments, users frequently defined endpoints using Spring XML configurations within a jbossws-cxf.xml file. Modern WildFly 41 drops built-in Spring runtime dependencies in favor of standard Jakarta EE annotations and CDI. If you need to customize your CXF endpoints or wire interceptors on modern WildFly, do not write Spring XML. Instead, use JAX-WS handlers or CDI beans, or declare JBossWS features programmatically.
For more details about configuring legacy Apache CXF web services, you can refer to the historical wiki: http://community.jboss.org/wiki/JBossWS-StackCXFUserGuide
Compile and build your WAR file, then deploy it to your running WildFly 41 instance by copying it to the standalone/deployments/ directory or using the JBoss CLI. Once successfully deployed, navigate to the WildFly Management Console (typically at http://localhost:9990) or visit the application context to view the published services.
Develop a CXF client
You can call the service using standard JAX-WS API interfaces, but using Apache CXF's JaxWsProxyFactoryBean provides programmatic control over the transport layer, logging, and performance tuning.
Here is a modern client implementation using Apache CXF APIs:
package com.sample;
import org.apache.cxf.ext.logging.LoggingInInterceptor;
import org.apache.cxf.ext.logging.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class Client {
public static void main(String[] args) throws Exception {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
// Modern CXF logging interceptors
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(Math.class);
factory.setAddress("http://localhost:8080/Samplews/MathWS");
Math client = (Math) factory.create();
System.out.println("Server said: " + client.sum(3, 4));
}
}
Advanced Modern Configuration for WildFly 41
1. Performance & Timeouts
Configuring connection and read timeouts is vital to prevent client threads from hanging indefinitely when remote services become unresponsive. There are two primary ways to set these timeouts: portable Jakarta XML Web Services API and CXF-specific APIs.
Standard Jakarta XML Web Services API (Portable)
import jakarta.xml.ws.BindingProvider;
import java.util.Map;
// Cast your client proxy to BindingProvider
BindingProvider bp = (BindingProvider) client;
Map<String, Object> requestContext = bp.getRequestContext();
// Set timeout in milliseconds (Jakarta standard properties)
requestContext.put("jakarta.xml.ws.client.connectionTimeout", 5000); // 5 seconds
requestContext.put("jakarta.xml.ws.client.receiveTimeout", 10000); // 10 seconds
CXF-Specific API (Fine-grained Control)
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
Client cxfClient = ClientProxy.getClient(client);
HTTPConduit httpConduit = (HTTPConduit) cxfClient.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setConnectionTimeout(5000); // 5 seconds
policy.setReceiveTimeout(10000); // 10 seconds
httpConduit.setClient(policy);
2. Interceptors vs. JAX-WS Handlers
It is important to understand when to use JAX-WS Handlers versus CXF Interceptors:
- JAX-WS Handlers: Part of the standard Jakarta XML Web Services specification. They are portable across other application servers (like Open Liberty or GlassFish). Handlers operate on
LogicalMessageContextorSOAPMessageContext, which can introduce processing overhead due to complete SOAP DOM tree parsing. - CXF Interceptors: Native to Apache CXF. They are organized into distinct processing "Phases" (e.g., RECEIVE, PRE_STREAM, PRE_PROTOCOL). They provide low-level XML stream access via StAX, offering superior performance and enabling fine-grained manipulations before the SOAP payload is fully read into memory.
3. Robust Security Configuration
In modern enterprise architectures, transmitting credentials over unencrypted HTTP channels is highly insecure. Always mandate HTTPS/TLS for web service communication. When configuring message-level security, use WS-Security (WSS4J) to secure transport transactions.
You can easily configure server-side WS-Security on WildFly by adding security annotations directly to your service class, or by configuring the webservices subsystem using WildFly CLI commands to leverage your elytron security domains:
/subsystem=webservices:write-attribute(name=statistics-enabled, value=true)
4. Cloud & Container Deployments (Kubernetes/OpenShift)
When deploying WildFly 41 in containerized environments behind load balancers, ingress controllers, or reverse proxies (like NGINX), the generated WSDL must reflect the public-facing domain name and protocol (HTTPS) rather than internal container IPs.
Use the WildFly JBoss CLI to instruct the server to dynamically rewrite WSDL locations based on incoming HTTP request headers, or define a static external hostname:
# Force WildFly to modify the SOAP address inside WSDL with incoming request details
/subsystem=webservices:write-attribute(name=modify-wsdl-address, value=true)
# Alternatively, define a fixed external host for rewriting
/subsystem=webservices:write-attribute(name=wsdl-host, value="api.example.com")
/subsystem=webservices:write-attribute(name=wsdl-secure-port, value=443)
Testing Modern SOAP Web Services
Avoid relying on outdated IDE-bound wizards for SOAP validation. To verify your services, adopt modern automation tools:
- SoapUI / ReadyAPI: Create robust integration tests against the dynamic WSDL URL (e.g.,
http://localhost:8080/Samplews/MathWS?wsdl). - Curl: Issue a POST request containing raw SOAP XML payloads directly to your endpoint to test routing and raw responses.
- JUnit 5 & Arquillian / Testcontainers: Write automated integration tests that spin up lightweight WildFly container instances to verify service packaging and deployment compatibility.
Frequently Asked Questions (FAQs)
1. How do I migrate my old JBoss AS 5 / JBoss AS 7 endpoints to WildFly 41?
Change your dependency coordinates from javax.jws:* to jakarta.jws:* and javax.xml.ws:* to jakarta.xml.ws:*. Replace old Spring-based configuration descriptors (like jbossws-cxf.xml) with standardized Jakarta EE annotations. Ensure you package your web service within a standard WAR file deployable to modern WildFly runtimes.
2. Why am I getting class loading errors with CXF packages on WildFly?
WildFly isolates deployment dependencies. If you need to access native Apache CXF APIs (like JaxWsProxyFactoryBean or interceptors) in your server deployment, declare the dependency in your application's jboss-deployment-structure.xml:
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.apache.cxf" />
</dependencies>
</deployment>
</jboss-deployment-structure>
3. How do I enable schema validation on my WildFly CXF endpoint?
You can easily enforce schema validation on incoming SOAP payloads to reject malformed XML. Simply add the @org.apache.cxf.annotations.SchemaValidation annotation directly to your service class implementation.
Recommended Articles
Developing SOAP Web Services on WildFly 41 (Jakarta EE 11) with Apache CXF
Learn how to develop, deploy, and secure Jakarta XML Web Services (SOAP) on WildFly 41.0.1.Final and Jakarta EE 11 using Apache CXF, WS-Security, and modern testing tools.
Apache CXF Interceptors on WildFly 41 and Jakarta EE 11
Learn how to write, configure, and customize Apache CXF Interceptors on WildFly 41.0.1.Final and Jakarta EE 11. Upgrade from legacy configuration to modern Jakarta XML Web Services.
Using Axis Web Services with JBoss: Migration to modern JAX-WS with WildFly 41
Learn how to migrate legacy Apache Axis SOAP web services from JBoss to modern Jakarta EE 11 and JAX-WS on WildFly 41.0.1.Final using Apache CXF with secure HTTPS configurations and debugging.
Enhance Your Enterprise Java Applications with HTTP Basic Authentication and Apache CXF Interceptors
Learn how to implement HTTP Basic Authentication for JAX-WS Web services and explore alternative authentication mechanisms using Apache CXF Interceptors. #Java #Middleware #CloudNative