IBM WebSphere Application Server (WAS) 為企業級 Java EE 容器,提供健全的事務、安全、執行緒、連線池管理。本文針對 Spring Framework 2.5+ 與 Hibernate 於 WAS V7/V8/V9 環境的整合,提供經實戰驗證的配置最佳實踐,避開常見類別載入衝突、事務管理陷阱與非受管執行緒風險。
Web 模組 web.xml / EJB 模組 ejb-jar.xml 宣告 resource-ref:
<resource-ref>
<res-ref-name>jdbc/springdb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Spring XML 以 JndiObjectFactoryBean 或 <jee:jndi-lookup> 代理:
<jee:jndi-lookup id="wasDataSource"
jndi-name="jdbc/springdb"
cache="true"
resource-ref="true"
lookup-on-startup="false"
proxy-interface="javax.sql.DataSource"/>
關鍵:resource-ref="true" 讓 Spring 自動補上 java:comp/env/ 前綴,確保查找受容器管理的資源。
Spring 2.5+ 提供 org.springframework.transaction.jta.WebSphereUowTransactionManager,委派 WAS UOWManager 介面,支援完整傳播行為(含 REQUIRES_NEW、NOT_SUPPORTED)。
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
禁用:JtaTransactionManager (autodetectTransactionManager=false) 僅支援有限傳播行為;WebSphereTransactionManagerFactoryBean 依賴內部 SPI,不受支援。
<jee:jndi-lookup id="jmsConnectionFactory" jndi-name="jms/myCF" resource-ref="true"/>
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destinationResolver" ref="jmsDestResolver"/>
</bean>
<bean id="msgListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destination" ref="jmsQueue"/>
<property name="messageListener" ref="messageListener"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="taskExecutor" ref="workManagerTaskExecutor"/>
</bean>
<bean id="workManagerTaskExecutor"
class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default"/>
</bean>
注意:生產環境高可用/負載管理場景,建議直接使用 J2EE MDB 替代 Spring Message-driven POJO。
persistence.xml 設定 JTA 資料源與 OpenJPA managed 模式:
<persistence-unit name="default" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>java:comp/env/jdbc/springdb</jta-data-source>
<properties>
<property name="openjpa.TransactionMode" value="managed"/>
<property name="openjpa.ConnectionFactoryMode" value="managed"/>
<property name="openjpa.jdbc.DBDictionary" value="db2"/>
</properties>
</persistence-unit>
EntityManager 注入:@PersistenceContext EntityManager em; + PersistenceAnnotationBeanPostProcessor。
Quartz、JDK Timer、Spring 其他 TaskExecutor 皆會啟動非受管執行緒,違反 Java EE 規範,導致資源洩漏、無法優雅關閉。WAS 管理主控台配置 WorkManager (Resources → Asynchronous beans),Spring 僅注入 JNDI 名稱。
WAS MBean ObjectName 為完整限定名稱 (WebSphere:cell=...,name=...,type=...)。實作 ObjectNamingStrategy 封裝命名邏輯,注入 MBeanExporter,確保應用卸載時正確取消註冊。
PARENT_LAST (模組級) 或 EAR 級 PARENT_LAST 配合 Classloader isolation<property name="hibernate.connection.datasource">java:comp/env/jdbc/myDSRef</property>
<!-- CMT 容器管理事務 -->
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</property>
<property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</property>
<!-- BMT Bean 管理事務 -->
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
<property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</property>
<property name="jta.UserTransaction">java:comp/UserTransaction</property>
支援 WAS V6.0.2.19+ / V6.1.0.9+。舊版內部介面配置不受支援。
OpenSessionInViewFilter 搭配 Spring 事務,避免長會話序列化/叢集複寫問題。HttpSession 僅存放極小斷離物件 (10-50KB),大型快取改用 ObjectGrid / DistributedObjectCache。
org.hibernate.cache.CacheProvider 介面包裝 DistributedMap / DistributedObjectCache 或 ObjectGridhibernate.cache.provider_class 指向自訂實作可共享連線不支援動態切換隔離等級。
SCA 組件無 resource-ref,無法直接用 Hibernate。兩種門面模式:
| 禁忌 | 後果 | 正確做法 |
|---|---|---|
| 使用 NativeJdbcExtractor / WebSphereNativeJdbcExtractor | 繞過連線池/事務/追蹤,依賴內部類會隨補丁失效 | 用 WSCallHelper 存取廠商擴充 API |
| Spring registerShutdownHook | 啟動非受管執行緒,阻礙優雅關閉 | 用 ServletContextListener / @PreDestroy 生命週期回調 |
| WeakReferenceMonitor (Spring EJB 便利類) | 產生非受管執行緒 | 避免使用,自行管理 EJB 引用 |
| Quartz / JDK Timer / SimpleAsyncTaskExecutor | 非受管執行緒 | 改用 WorkManagerTaskExecutor |
| 直接使用 WAS 內部 SPI (com.ibm.*) | 升級風險極高,不受 IBM 支援 | 僅用公開 Java EE / Spring / WAS 公開 API |
Spring + Hibernate 在 WebSphere 上穩健運行的關鍵在於:尊重容器契約——資源由容器管理、事務由容器協調、執行緒由容器調度、類別載入隔離避免衝突。將框架配置對齊 Java EE 規範與 WAS 公開 API,即可同時享受 Spring 開發效率與 WAS 企業級可靠性。