SpringSide 2.0 內建 XFire,但實測配置頻報錯。改用 Apache CXF 2.x(JAX-WS 標準實作)後即刻成功。本文記錄從下載 Jar、解決 PermGen OOM、替換 Servlet、定義 SEI/實作類、Spring 配置端點、客戶端代理生成的全過程,供 SpringSide 遷移者參考。
下載 apache-cxf-2.0-incubator.zip,將 lib/ 下列 Jar 複製至 webapp/WEB-INF/lib/:
commons-logging-1.1.jar
geronimo-activation_1.1_spec-1.0-M1.jar
geronimo-annotation_1.0_spec-1.1.jar
geronimo-javamail_1.4_spec-1.0-M1.jar
geronimo-servlet_2.5_spec-1.1-M1.jar
geronimo-ws-metadata_2.0_spec-1.1.1.jar
jaxb-api-2.0.jar, jaxb-impl-2.0.5.jar
jaxws-api-2.0.jar
neethi-2.0.jar
saaj-api-1.3.jar, saaj-impl-1.3.jar
stax-api-1.0.1.jar
wsdl4j-1.6.1.jar
wstx-asl-3.2.1.jar
XmlSchema-1.2.jar
xml-resolver-1.2.jar
cxf-2.0-incubator.jar

若專案已有同名舊版 Jar,建議刪除舊版保留 CXF 版本;保留 XFire Jar 亦不衝突,但建議清理。

CXF 依賴 Jar 較多,加上 SpringSide 原有大量第三方庫,啟動易爆 java.lang.OutOfMemoryError: PermGen space。
編輯 SpringSide2.0/misc/servers/tomcat-5.5.17/bin/catalina.bat,在 set JAVA_OPTS= 行追加:
set JAVA_OPTS=%JAVA_OPTS% -Xms512m -Xmx1024m -XX:MaxNewSize=512m -XX:MaxPermSize=512m
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties":noJuli
Java 8+ 專案請改用 -XX:MaxMetaspaceSize=512m,PermGen 已移除。
<!-- 原 XFire -->
<servlet>
<servlet-name>xfire</servlet-name>
<servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>xfire</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
<!-- 改為 CXF -->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
// SEI
package com.yumdays.service;
import javax.jws.WebService;
import com.yumdays.model.SUser;
@WebService
public interface IndexService {
boolean addUser(SUser user, String adminName, String adminPassword);
}
// 實作類
package com.yumdays.service;
import javax.jws.WebService;
import com.yumdays.model.SUser;
@WebService(endpointInterface = "com.yumdays.service.IndexService")
public class IndexServiceImpl implements IndexService {
public boolean addUser(SUser user, String adminName, String adminPassword) {
// TODO: 呼叫索引伺服器本地邏輯或遠端 RPC
return false;
}
}
@WebService 標註即啟用 JAX-WS 端點,無需額外介面/實作分離檔案。endpointInterface 屬性明確綁定 SEI,避免 CXF 反射推導失誤。cxf-beans.xml放置於 src/resource/spring/,刪除所有 XFire 相關 XML。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="https://cxf.apache.org/jaxws"
xsi:schemaLocation="
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-2.0.xsd
https://cxf.apache.org/jaxws https://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<bean id="indexServiceBean" class="com.yumdays.service.IndexServiceImpl"/>
<jaxws:endpoint id="indexService"
implementor="#indexServiceBean"
address="/IndexService"/>
</beans>
address="/IndexService" 為相對路徑,完整 URL 為 https://host:port/context/service/IndexService。import 分別載入 CXF 核心 Bean、SOAP 擴展、Servlet 傳輸配置。重新建構、部署、啟動 Tomcat,瀏覽:
https://www.yumdays.com/service/IndexService?wsdl
應見標準 WSDL 文檔,含 addUser 操作、SUser 複雜類型定義、SOAP 1.1/1.2 綁定。

消費端同樣用 CXF + Spring,零代碼生成代理:
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="https://cxf.apache.org/jaxws"
xsi:schemaLocation="...同樣的 schemaLocation...">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="com.yumdays.service.IndexService"/>
<property name="address" value="https://www.yumdays.com/service/IndexService"/>
</bean>
<bean id="client" class="com.yumdays.service.IndexService"
factory-bean="clientFactory" factory-method="create"/>
</beans>
注入 client Bean 即可直接呼叫 client.addUser(...),CXF 透明處理 SOAP 封裝/解析、異常映射。
jaxws:properties 設定 ws-security.username/password 或簽名加密。@XmlMimeType,端點配置 @BindingType(SOAP12HTTP_MTOM_BINDING)。AsyncClientTransportFeature 或 Dispatch<Source>。LoggingInInterceptor/LoggingOutInterceptor 或整合 Log4j/Slf4j。