Using Spring CXF descriptors in WildFly

TL;DR: Deploying custom Spring-backed CXF descriptors on WildFly 41.0.1.Final requires transitioning to Jakarta EE 11 (jakarta.* namespaces) and Spring Framework 6+. This guide explains how to install modern Spring libraries as a custom WildFly module, configure your jbossws-cxf.xml deployment descriptor, manage SOAP timeouts, and optimize performance.

In modern enterprise environments, some systems still require consuming legacy or customized Spring cxf.xml or jbossws-cxf.xml descriptors. To achieve this on WildFly, the Spring framework libraries must be accessible to the thread classloader of the deployment. For the modern WildFly web services stack (powered by the reference implementation, JBossWS-CXF / Apache CXF) to correctly locate and process Spring classes, you must configure a custom WildFly module named org.springframework.spring.

This tutorial has been fully updated for WildFly 41.0.1.Final and Jakarta EE 11. Because Jakarta EE 11 relies entirely on the jakarta.* namespace (specifically jakarta.xml.ws, jakarta.jws, and jakarta.xml.bind), you must use Spring Framework 6.x (or later) which natively supports Jakarta EE namespaces. Attempting to use older Spring 5.x (or prior) libraries will cause runtime class-cast and initialization exceptions due to legacy javax.* dependencies.

Step 1: Installing Spring Libraries as a WildFly Module

To configure Spring inside WildFly, you need to create the appropriate directory layout under your WildFly home directory. Navigate to your WildFly installation directory and create the following path:

mkdir -p JBOSS_HOME/modules/system/layers/base/org/springframework/spring/main

Copy the required Spring Framework 6+ JAR files into this directory. Then, create a module.xml file in the same directory. Below is the modern, optimized module.xml structure adjusted for Jakarta EE 11 dependencies:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.9" name="org.springframework.spring">
   <resources>
      <resource-root path="spring-core-6.1.12.jar" />
      <resource-root path="spring-beans-6.1.12.jar" />
      <resource-root path="spring-context-6.1.12.jar" />
      <resource-root path="spring-expression-6.1.12.jar" />
      <resource-root path="spring-tx-6.1.12.jar" />
      <resource-root path="spring-aop-6.1.12.jar" />
   </resources>
   <dependencies>
      <module name="jakarta.api" />
      <module name="jakarta.annotation.api" />
      <module name="jakarta.xml.ws.api" />
      <module name="org.apache.commons.logging" />
      <module name="org.jboss.vfs" />
   </dependencies>
</module>

Note: The legacy spring-asm module has been fully integrated into spring-core in modern versions of Spring and is no longer required. All legacy JBoss AS 7 / javax.api modules have been replaced with their standard Jakarta counterparts.

Once Spring is made available via this system module, the Apache CXF Bus initialization routines can correctly locate and process your custom Spring beans and descriptor configurations.

Step 2: Configuring Server-Side Web Services (jbossws-cxf.xml)

On the server side, WildFly's JBossWS stack automatically scans and processes a custom descriptor named jbossws-cxf.xml when the deployment is linked to the Spring module. To structure this correctly within your deployment, use the following rules:

  • For POJO deployments (WAR files): Place the descriptor in the WEB-INF/ directory.
  • For EJB3 deployments (JAR files): Place the descriptor in the META-INF/ directory.

To ensure your web application loads this module, configure a jboss-deployment-structure.xml file in your deployment's metadata folder:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
   <deployment>
      <dependencies>
         <module name="org.springframework.spring" export="true" />
      </dependencies>
   </deployment>
</jboss-deployment-structure>

Here is an updated jbossws-cxf.xml configuration example. This modern configuration maps endpoints and sets up connection timeouts and modern WS-Security:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
       xsi:schemaLocation="
          http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://cxf.apache.org/jaxws 
          http://cxf.apache.org/schemas/jaxws.xsd
          http://cxf.apache.org/transports/http/configuration
          http://cxf.apache.org/schemas/configuration/http-conf.xsd">

   <!-- Endpoint configuration -->
   <jaxws:endpoint id="SampleWS" 
                   address="https://localhost:8443/Samplews" 
                   implementor="com.sample.SampleWS">
      <jaxws:invoker>
         <bean class="org.jboss.wsf.stack.cxf.JBossWSInvoker" />
      </jaxws:invoker>
      
      <!-- Apache CXF Interceptors -->
      <jaxws:inInterceptors>
         <bean class="org.apache.cxf.ext.logging.LoggingInInterceptor" />
      </jaxws:inInterceptors>
      <jaxws:outInterceptors>
         <bean class="org.apache.cxf.ext.logging.LoggingOutInterceptor" />
      </jaxws:outInterceptors>
   </jaxws:endpoint>

   <!-- Client Connection and Receive Timeout configuration -->
   <http-conf:conduit name="*.http-conduit">
      <http-conf:client ConnectionTimeout="5000" ReceiveTimeout="15000" />
   </http-conf:conduit>
</beans>

Security, Timeouts, and Performance

  • Secure Transport (HTTPS/TLS): When writing SOAP services on WildFly 41, avoid plain HTTP and basic authentication. Always configure WildFly's Elytron subsystem to enforce TLS and leverage security standards like WS-Security (WSS) within your CXF configurations for message-level encryption and signing.
  • SOAP Handlers vs. Apache CXF Interceptors: When extending web services, distinguish between standard JAX-WS handlers (which implement jakarta.xml.ws.handler.Handler and are portable across any EE runtime) and native Apache CXF interceptors. Interceptors are more efficient because they run on CXF's internal message-processing pipelines (phase-based), bypassing standard SOAP DOM overhead.
  • Timeout Management: Connection timeouts (how long to wait to establish a TCP channel) and receive timeouts (how long to wait for a SOAP response) should be explicitly set via <http-conf:conduit> as shown above to prevent thread exhaustion on WildFly under high-load production scenarios.

Testing and Diagnostics

To verify that your services are deployed correctly, avoid obsolete IDE tooling or old eclipse plugins. Instead, use modern tools like SoapUI, curl, or automated JUnit 5 tests. You can inspect the loaded CXF engine configuration and active endpoints by querying the WildFly Management CLI:

/subsystem=webservices:read-resource(recursive=true)

If you are deploying web services within cloud environments (such as Kubernetes or Red Hat OpenShift), remember that modern reverse proxies and ingress controllers often rewrite external hostnames. Make sure to update your WildFly configuration to modify the WSDLIp/WSDLHost dynamically via CLI:

/subsystem=webservices:write-attribute(name=wsdl-host, value="jbossws.undefined")

SOAP vs. REST in Enterprise Architectures

While RESTful architectures (utilizing Jakarta RESTful Web Services / JAX-RS) have become dominant for simple public APIs, SOAP remains highly relevant in enterprise settings. SOAP web services offer formal contracts (WSDL), built-in security specifications (WS-Security), transaction support (WS-Coordination), and robust reliable messaging frameworks (WS-Reliability). Integrating custom CXF descriptors allows developers to bridge modern Jakarta EE runtimes with robust enterprise heritage integrations.

Do you want some more Spring stuff ? check Spring Boot Tutorials !

Frequently Asked Questions (FAQs)

Q: Why does my deployment fail with a ClassNotFoundException for spring classes after upgrading to WildFly 41?

A: This is usually because the Spring module is missing from the server's modules directory, or your deployment lacks a jboss-deployment-structure.xml file referencing the org.springframework.spring module.

Q: Can I use Spring 5.x JARs inside my WildFly 41 module configuration?

A: No. WildFly 41 is built on Jakarta EE 11, which utilizes the jakarta.* namespace. Spring 5.x depends on legacy javax.* namespaces and will fail at runtime. You must upgrade to Spring 6.x which is fully compatible with Jakarta EE.

Q: What is the benefit of using jbossws-cxf.xml instead of standard Jakarta EE annotations?

A: While annotations (such as @WebService) cover basic integrations, jbossws-cxf.xml allows you to access low-level CXF capabilities. This includes custom CXF interceptors, advanced schema validation configurations, specific HTTP-conduit timeouts, and custom WS-Security configurations that are not easily expressible in standard annotations.


Recommended Articles

Deploying a JPA-Based Spring Boot Application on WildFly 10: A Step-by-Step Guide

Learn how to deploy a Spring Boot application with JPA on WildFly 10, including setup and configuration for a RESTful API.

How to Deploy Spring Boot 4 and 3 Applications on WildFly

Step-by-step guide to deploying Spring Boot 4 and 3 WAR applications on WildFly. Learn pom.xml configuration, SpringBootServletInitializer setup, and log conflict troubleshooting.

Develop a Web Application with PrimeFaces, Spring JDBC, and CDI - A Comprehensive Guide

Learn how to develop a robust web application using PrimeFaces for UIs, Spring JDBC for persistence, and CDI as glue. #JavaEE #SpringJDBC #CDI #WildFly31

Using Spring Retry to Consume REST Services with Java

Learn how to use Spring Retry to automatically retry failed REST service calls and improve application reliability.