DEV Community

binbingoloo
binbingoloo

Posted on

"SOAP 1.1 endpoint already registered" - Spring 6 and CXF 4 Integration Issue

During our recent upgrade from Spring 3 to Spring 6 while using CXF 4, we encountered a perplexing issue:

SOAP 1.1 endpoint already registered on address /soap/xxxService

Root Cause

We discovered that Spring 6's enhanced bean lifecycle management conflicts with CXF's endpoint registration mechanism. Here's what happens:

1. Spring 6 Configuration Loading Changes

Spring 6 introduced stricter bean definition and lifecycle management, which can cause CXF endpoints to be registered multiple times through different mechanisms:

// Multiple registration paths:
// 1. Auto-discovery via @WebService annotations
// 2. Explicit XML configuration
// 3. Java-based configuration
// 4. CXF's internal auto-configuration
Enter fullscreen mode Exit fullscreen mode

2. The Duplicate Registration Scenario

Without proper CXF initialization, endpoints get registered multiple times:

<!-- XML Configuration -->
<jaxws:endpoint id="xxxService" 
                implementor="#xxxServiceImpl"
                address="/soap/xxxService" />

<!-- Component Scanning might also pick up the same service -->
<context:component-scan base-package="com.example.service" />
Enter fullscreen mode Exit fullscreen mode

3. Missing CXF Core Configuration

Spring 6 no longer automatically loads certain CXF configurations that were previously handled implicitly, leading to an improperly initialized CXF Bus and DestinationRegistry.

Why Importing CXF Configuration Files Solves the Issue

The Role of cxf.xml

The META-INF/cxf/cxf.xml file contains essential CXF infrastructure beans:

<beans xmlns="http://www.springframework.org/schema/beans"...>
    <!-- CXF Bus - the core of CXF -->
    <bean id="cxf" class="org.apache.cxf.bus.spring.SpringBus" destroy-method="shutdown">
        <!-- ... -->
    </bean>

    <!-- Ensures Bus singleton pattern -->
    <bean id="org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor"
          class="org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor">
        <!-- ... -->
    </bean>
</beans>
Enter fullscreen mode Exit fullscreen mode

Solution

Add the imports to your Spring configuration:

<?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"
       xsi:schemaLocation="...">

    <!-- Import CXF core configurations -->
    <import resource="classpath:META-INF/cxf/cxf.xml"/>

    <!-- Your endpoint definitions -->
    <jaxws:endpoint id="xxxService"
                    implementor="com.example.service.XxxServiceImpl"
                    address="/soap/xxxService">
        <jaxws:properties>
            <entry key="schema-validation-enabled" value="true"/>
        </jaxws:properties>
    </jaxws:endpoint>
</beans>
Enter fullscreen mode Exit fullscreen mode

The imported configurations guarantee that only one CXF Bus is created and properly initialized. The DestinationRegistry from cxf-servlet.xml maintains a single registry of all endpoints Explicit configuration takes precedence over any auto-discovery mechanisms.

Top comments (0)