程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 將Spring和Hibernate與WebSphere Application Server一起使用

將Spring和Hibernate與WebSphere Application Server一起使用

編輯:關於JAVA

如果您考慮將 Spring 或 Hibernate 與 IBM® WebSphere® Application Server 一起使用,則本文將向您闡述如何為各種 WebSphere Application Server 場景配置這些框架。本文不是對任一框架的詳盡評論,而 是幫助您成功實現此類場景的重要參考。(針對 Spring Framework 2.5 和 WebSphere Application Server V7 進行了更新。)

引言

Spring Framework(通常稱為 Spring)是一個開放源代碼項目,目的是 為了使 J2EE™ 環境更具可訪問性。Spring 為簡單 Java™ 對象提 供框架,使這些對象可以通過包裝類和 XML 配置使用 J2EE 容器。Spring 的目 標是為這些項目提供顯著的好處,提高這些項目的開發效率和運行時性能,同時 改進測試覆蓋率和應用程序質量。

Hibernate 是開放源代碼持久性和查 詢框架,提供傳統 Java 對象(Plain Old Java Object,POJO)到關系數據庫 表的對象-關系映射,以及數據查詢和檢索功能。

盡管許多組織感興趣的 是了解使用這些框架能夠獲得什麼好處,但 IBM 希望讓使用這些框架的客戶知 道,他們可以通過 WebSphere Application Server 以穩健和可靠的方式做到這 一點。本文介紹這些框架如何與 WebSphere Application Server 一起使用,並 介紹針對各種用例的最佳實踐,以幫助您盡快開始使用 Spring 或 Hibernate。

使用 Spring

通常將 Spring 描述為輕量級容器環境,但是將其 描述為用於簡化開發的框架可能更適當。Spring Framework 由 Interface21 根 據 Rod Johnson 發表的關於依賴項注入設計模式的出版物開發而成。Spring 可 以在獨立應用程序中使用,或與應用程序服務器一起使用。其主要概念是使用依 賴項注入和面向方面的編程來簡化和平穩地進行從開發到測試再到生產的轉換。

涉及 Spring 的最常用場景之一是使用簡單的 Java Bean 類配置並驅動業務 邏輯。 Spring 文檔應該提供了使用 Spring Bean 構建應用程序的足夠信息, 其中沒有提供任何特定於 WebSphere 的內容。以下部分將描述在 WebSphere Application Server 上使用 Spring 的一些使用場景。根據本文的建議開發的 Spring 應用程序應該能夠毫無問題地在 WebSphere Application Server 或 WebSphere Application Server Network Deployment 環境中執行。

除明確指出以外,本文提供的信息適用於所有平台上的 WebSphere Application Server 版本 6.0.2.x、6.1.x 和 7.0.x。

表示層注意事項

本部分介紹與在基於 Web 的表示層中使用 Spring 相關的注意事項。

Web MVC 框架

Spring 的 Web MVC 框架很長時間以來一直是其他框架的替代框架。直接由 WebSphere Application Server 交付、使用和支持的 Web MVC 框架包括 JavaServer Faces (JSF) 和 Struts。Spring 文檔描述了如何將 Spring 與這 些 Web 框架集成。盡管 WebSphere Application Server 支持使用上面的任何 MVC,但 IBM 僅為 WebSphere Application Server 附帶的框架提供產品支持。

Portlet MVC 框架

Spring 還提供了一個 Portlet MVC 框架(該框架鏡像 Spring Web MVC 框 架),而且在 WebSphere Portal V6.0 和 WebSphere Application Server V6.1 Portlet 容器中運行。(有關 Spring Portlet 的示例集,請參見 Spring Portlet MVC。)在 WebSphere Application Server V6.1 Portlet 容器中運行 Portlet 需要創建附加的 Web 應用程序,以定義 Portlet 的布局和聚合。從 WebSphere Application Server 信息中心和文章 Portlet 容器介紹中可以獲得 關於如何使用 Portlet 聚合器標記庫的信息。通常的做法是結合使用 JSF 和 Portlet 進行呈現。關於如何將 Spring、Hibernate、JSF 和 WebSphere Portal 組合起來的信息,請參見使用 IBM WebSphere Portal 配置 Hibernate 、Spring、Portlets 和 OpenInSessionViewFilter。

數據訪問注意事項

本部分介紹與訪問事務中的數據的 Spring Bean 配置相關的注意事項。

Spring Framework 實際上使用一個容器管理層(在 J2EE 環境中委托給基礎 J2EE 運行時)包裝 Spring Bean。下面將介紹應如何配置 Spring Bean,以便 Spring Framework 可以正確地向 WebSphere Application Server 運行時做出 委托並與之集成。

訪問 WebSphere Application Server 中配置的數據源

WebSphere Application Server 管理在應用程序服務器執行環境中使用的資 源。需要訪問諸如 JDBC 數據源等資源的 Spring 應用程序應該利用 WebSphere 管理的資源。為此,請執行以下步驟:

在開發過程中,應該使用資源引用配置 WAR 模塊。例如:

<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>

對於 EJB JAR 文件,應該在需要訪問數據源的每個 EJB 中聲明同一資源引 用。

然後在 Spring 應用程序配置中聲明數據源代理 Bean,代理 Bean 引用 WebSphere 管理的資源提供者:

<bean id="wasDataSource"
   class="org.springframework.jndi.JndiObjectFactoryBean">
   <property name="jndiName"
     value="java:comp/env/jdbc/springdb"/>
   <property name="lookupOnStartup"
     value="false"/>
   <property name="cache"
     value="true"/>
   <property name="proxyInterface"
     value="javax.sql.DataSource"/>
</bean>

通過此代理 Bean 訪問數據源將會導致使用模塊配置的引用查找數據源,從 而能夠由 WebSphere Application Server 正確管理。請注意,jndiName 屬性 值與使用資源引用中聲明的資源引用名稱連接的模式 java:comp/env/ 匹配。

或者,在 Spring 2.5 以後的版本中,可以使用 <j2ee:jndi- lookup/> 方法完成此匹配。請注意 jndiName 屬性如何匹配資源引用中聲明 的資源引用名稱與 resource-ref="true" 屬性相結合的實際值:

<jee:jndi-lookup id=" wasDataSource "
   jndi-name="jdbc/springdb"
   cache="true"
   resource-ref="true"
   lookup-on-startup="false"
   proxy-interface="javax.sql.DataSource"/>

然後,Spring 應用程序可以在適當情況下使用數據源代理 Bean。

將應用程序部署到 WebSphere Application Server 時,必須以常規方式配 置資源提供者和資源數據源,以便由 Spring 應用程序資源引用使用。在部署過 程中,在模塊的部署描述符中聲明的資源引用將綁定到應用程序服務器配置的數 據源。

使用 JDBC 本機連接

當各種 JDBC 操作需要與本機 JDBC 資源交互時,Spring 可提供訪問本機連 接的機制。當在 JdbcTemplate 類上設置了 NativeJdbcExtractor 類時, Spring JdbcTemplate 類才可以利用此功能。設置 NativeJdbcExtractor 類後 ,當與 WebSphere Application Server 一起使用時,Spring 總是向下找到本 機 JDBC 連接。這將忽略以下 WebSphere 服務質量功能和優點:

連接處理跟蹤和再關聯

連接共享

參與事務

連接池管理

這帶來的另一個問題是 WebSphereNativeJdbcExtractor 類將依賴於內部 WebSphere 適配器類。這些內部類可能因 WebSphere Application Server 的版 本而異,並且以後可能更改,從而破壞依賴於此功能的應用程序。

在 WebSphere Application Server 上不支持使用 NativeJdbcExtractor 類 實現(例如 WebSphereNativeJdbcExtractor),您應避免需要使用該類的場景 。替代方案是使用 WebSphere Application Server WSCallHelper 類來訪問非 標准供應商的數據源擴展。

使用 Spring 處理事務

WebSphere Application Server 為事務處理和管理與資源提供者的連接提供 了一個穩健和可伸縮的環境。無論是否在使用全局事務,與 JDBC、JMS 和 Java Connector 資源適配器的連接均由 WebSphere Application Server 管理;甚至 在缺少全局事務時,始終存在一個運行時上下文,在該上下文中可以訪問所有資 源提供者連接。WebSphere Application Server 將此運行時上下文稱為本地事 務容器 (LTC) 作用域;在缺少全局事務時始終存在一個 LTC,並且無論是存在 全局事務還是 LTC,資源訪問始終由運行時管理。為確保事務上下文管理的完整 性,以便可以正確管理事務資源,WebSphere Application Server 不向 WebSphere Application Server 中部署的應用程序或應用程序框架公開 javax.transaction.TransactionManager 接口。

在 Spring 中,有許多方法可以驅動事務控制下的資源更新,這包括編程形 式和聲明形式。聲明形式包括 Java Annotation 和 XML 描述符形式。如果將 Spring 2.5 與 WebSphere Application Server V6.0.2.19 或 V6.1.0.9 或者 更高版本一起使用,則可以利用對 Spring 的聲明式事務模型的完全支持。 Spring 2.5 有一個新的用於 WebSphere Application Server 的 PlatformTransactionManager 類,名為 WebSphereUowTransactionManager。該 類利用 WebSphere Application Server 的受支持 UOWManager 接口進行事務上 下文管理。通過 WebSphere Application Server 的 UOWManager 類管理事務劃 分可以確保在訪問資源提供者時始終可以使用適當的全局事務或 LTC 上下文。 不過,早期版本的 Spring 使用了內部 WebSphere 接口,以犧牲 Web 和 EJB 容器功能為代價來管理資源,並且不支持由應用程序使用。這會使容器處於未知 狀態,從而有可能導致數據損壞。

Spring 2.5 或更高版本中的聲明式事務劃分在 WebSphere Application Server 中受支持,它使用下面的聲明提供對 WebSphere 事務的支持:

<bean id="transactionManager"
   class="org.springframework.transaction.jta.WebSphereUowTransactionMana ger"/>

引用此聲明的 Spring Bean 然後將使用標准 Spring 依賴項注入來使用事務 支持,例如:

<bean id="someBean" class="some.class">
   <property name="transactionManager" >
     <ref bean="transactionManager"/>
   </property>
...
</bean>
<property name="transactionAttributes">
   <props>
     <prop key="*">PROPAGATION_REQUIRED</prop>
   </props>
   </property>

或者,在 Spring 2.5 以後的版本中,可以利用 Spring 的 AspectJ 支持。 在下面的示例中,可以將 <tx:advice/> 應用於應用程序的各個部分。這 指示所有以“get”開頭的方法都是 PROPAGATION_REQUIRED,並且所有以“set ”開頭的方法都是 PROPAGATION_REQUIRES_NEW。所有其他方法使用缺省事務設 置。

<tx:advice id="txAdvice" transaction- manager="transactionManager">
  <tx:attributes>
    <tx:method name="get*" propagation="REQUIRED" read-only="true" />
    <tx:method name="set*" propagation="REQUIRES_NEW" />
    <tx:method name="*" />
  </tx:attributes>
</tx:advice>

<aop:config/> 標記將那些設置應用於類 MyService 中定義的任何已 執行操作。

<aop:config>
  <aop:pointcut id="myServiceOperation"
    expression="execution(* sample.service.MyService.* (..))"/>
  <aop:advisor advice-ref="txAdvice"
    pointcut-ref="myServiceOperation"/>
</aop:config>

用於聲明事務設置的另一種替代機制是使用基於 Spring 注釋的事務支持。 這要求使用 Java 5+,因此無法與 WebSphere Application Server V6.0.2.x 一起使用。

將以下內容添加到 Spring.xml 配置:

<tx:annotation-driven/>

然後應該使用 @Transactional 注釋對需要事務屬性的任何方法進行標記:

@Transactional(readOnly = true)
public String getUserName()
{ ...

請注意,只能將 @Transactional 注釋用於注釋公共方法。

WebSphereUowTransactionManager 支持每個 Spring 事務屬性:

PROPAGATION_REQUIRED

PROPAGATION_SUPPORTS

PROPAGATION_MANDATORY

PROPAGATION_REQUIRES_NEW

PROPAGATION_NOT_SUPPORTED

PROPAGATION_NEVER

對於沒有提供 org.springframework.transaction.jta.WebSphereUowTransactionManager 的 早期 Spring 版本以及沒有提供 com.ibm.wsspi.uow.UOWManager 的 WebSphere Application Server V6.0.2.19 或 V6.1.0.9 之前的版本,WebSphere Application Server 中的事務支持通過以下 Spring 配置實現:

<bean id="transactionManager"
   class="org.springframework.transaction.jta.JtaTransactionManager">< BR>      <property name="autodetectTransactionManager"value="false" />
</bean>

此配置支持一組受限制的事務屬性,其中不包括 PROPAGATION_NOT_SUPPORTED 和 PROPAGATION_REQUIRES_NEW。Spring 類 org.springframework.transaction.jta.WebSphereTransactionManagerFactory Bean 也宣稱提供 PROPAGATION_NOT_SUPPORTED 和 PROPAGATION_REQUIRES_NEW 功能,它使用不受支持的內部 WebSphere Application Server 接口,不應將其 與 WebSphere Application Server 一起使用。

使用 Spring JMS

與訪問 JDBC 數據源類似,打算訪問 JMS 目的地的 Spring 應用程序必須確 保它們使用了 WebSphere 管理的 JMS 資源提供者。使用 Spring JndiObjectFactoryBean 作為 ConnectionFactory 代理的相同模式將確保可以 正確地管理 JMS 資源。

對於 JMS 消息發送或同步 JMS 消息接收,可以使用 JMSTemplates。這包括 通過 JNDI 和真正的動態解析使用 Spring 的動態目的地解析功能。

下面的示例演示了 ConnectionFactory 的資源引用配置。此引用在應用程序 部署過程中映射為指向應用程序服務器的 JNDI 命名空間中存儲的已配置托管 ConnectionFactory。ConnectionFactory 是執行消息處理所必需的,並且應該 將其注入 Spring JMSTemplate。

<resource-ref>
    <res-ref-name>jms/myCF</res-ref-name>
    <res-type>javax.jms.ConnectionFactory</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

現在應用程序中的 ConnectionFactory 有了已定義的 JNDI 名稱,可以對其 進行查找並將其注入 JMSTemplate:

<jee:jndi-lookup id="jmsConnectionFactory" jndi-name=" jms/myCF "/>
<bean id="jmsQueueTemplate"
     class="org.springframework.jms.core.JmsTemplate">
  <property name="connectionFactory">
    <ref bean="jmsConnectionFactory"/>
  </property>
  <property name="destinationResolver">
    <ref bean="jmsDestResolver"/>
  </property>
   ...
</bean>
<!-- A dynamic resolver -->
<bean id="jmsDestResolver" class="
    org.springframework.jms.support.destination.DynamicDestinationResolver "/>
<!-- A JNDI resolver -->
<bean id="jmsDestResolver"
   class=" org.springframework.jms.support.destination.JndiDestinationResolver"/& gt;

在運行時,JMSTemplate 可以基於目的地的 JNDI 名稱(在應用程序資源引 用中配置)或通過“動態解析”來基於 WebSphere Application Server 中配置 的目的地的管理名稱定位目的地;例如,對於綁定到 jms/myQueue 的 JNDI 引 用的 JMS myQueue 隊列:

JNDI 解析:

jmsTemplate.send("java:comp/env/jms/myQueue", messageCreator);

動態解析:

jmsTemplate.send("myQueue", messageCreator);

作為對 J2EE 消息驅動 Bean (MDB) 的替代,Spring 提供了用於異步地處理 入站 JMS 消息的消息驅動 POJO 模型。僅有一個 DefaultMessageListenerContainer 類將管理從 JMS 隊列到已配置的 POJO 的 消息,該 POJO 必須是 javax.jms.MessageListener 實現。

在 WebSphere Application Server 環境中,您還必須指定一個 WorkManagerTaskExecutor 類,這意味著 DefaultMessageListenerContainer 類將向服務器管理的線程池作出委托。正如上面描述過的,還應該通過 WebSphereUowTransactionManager 使用服務器的事務管理來配置 DefaultMessageListenerContainer。

<bean id="messageListener" class="sample.ExampleMessageListener" />
  <bean id="msgListenerContainer"
    class="org.springframework.jms.listener.DefaultMessageListenerContaine r">
    <property name="connectionFactory" ref="jmsConnectionFactory" />
    <property name="destination" ref="jmsQueue" />
    <property name="messageListener" ref="messageListener" />
    <property name="transactionManager" ref="transactionManager" />
    <property name="taskExecutor" ref="myTaskExecutor" />
  </bean>
  <bean id="myTaskExecutor"
    class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor" >
    <property name="workManagerName" value="wm/default" />
  </bean>
  <bean id="transactionManager"
    class="org.springframework.transaction.jta.WebSphereUowTransactionMana ger" />
  <jee:jndi-lookup id="jmsConnectionFactory" jndi-name="jms/CF1" />
  <jee:jndi-lookup id="jmsQueue" jndi-name="jms/jmsQueue" />

雖然可以使用此消息驅動 POJO 模型,但是在需要工作負載管理和/或高可用 性的 WebSphere Application Server 配置中,建議直接使用 J2EE 消息驅動 Bean (MDB)。請注意,不支持任何其他 Spring JMS MessageListenerContainer 類型,因為它們可以啟動非托管線程,而且還可能使用不應由 Java EE 環境中 的應用程序調用的 JMS API。

將 JPA 與 Spring 一起使用

EJB 3.0 規范將 Java Persistence API (JPA) 定義為提供可移植持久 Java 實體的方法。WebSphere Application Server V7 和 WebSphere Application Server V6.1 EJB 3 功能包都提供了 EJB 3 和 JPA 的實現;還可以將 JPA 的 Apache OpenJPA 實現與 WebSphere Application Server V6.1 一起使用(請參 見參考資料)。將 Spring 與 JPA 實現結合使用時,您應該直接使用 JPA,而 不是使用 Spring 的 JPA Helper 類(在 org.springframework.orm.jpa 包中 )。

WebSphere Application Server V6.1 及更高版本支持 JPA 應用程序托管的 實體管理器,該管理器可能是 JTA 或本地資源事務類型。JTA 實體管理器使用 應用程序服務器的基礎 JTA 事務支持,其事務劃分可以使用上面描述的標准 J2EE 技術或 Spring 的聲明式事務模型進行定義。

使用 JPA 的數據訪問對象 (DAO) 與 persistence.xml 打包在一起,後者為 應用程序使用的 JPA EntityManager 定義持久性上下文。例如,可以按下面的 方式設置用於 JTA 實體管理器(使用的數據源的 JNDI 名稱為 “java:comp/env/jdbc/springdb”)的 persistence.xml:

<persistence
  xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
  http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
   <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>
</persistence>

通過將 openjpa.TransactionMode 和 openjpa.ConnectionFactoryMode 屬 性設置為“managed”,JPA 實體管理器將事務和連接管理委托給 WebSphere Application Server。DAO 可以使用上面描述的 Spring 聲明式事務劃分。

還可以使用注釋風格的 JPA EntityManager 注入。這與標准 JPA 完全相同 :

@PersistenceContext
private EntityManager em;

您需要以下 XML 代碼將在 Spring XML 配置中啟用 EntityManager 注入:

<!-- bean post-processor for JPA annotations -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPo stProcessor"/>
|--10--------20--------30--------40--------50--------60--------70-- ------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|

Spring 將在此 XML 文件中定義的 EntityManagerFactory 的基礎上創建 EntityManager 。如果存在多個 EntityManagerFactory,則 Spring 將失敗。 使用以下方法中的一種(且僅一種)方法創建 EntityManagerFactory:

使用 Spring 的基本配置<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">< BR>   <property name="persistenceUnitName" value="default"/>
</bean>

使用 Spring 的高級配置<bean id="myEmf"
   class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryB ean">
|-------20--------30--------40--------50--------60--------70------- -80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
  <property name="dataSource" ref="ds"/>
</bean>
<jee:jndi-lookup
   id="ds"
   jndi-name="jdbc/ds"
   cache="true"
   expected-type="javax.sql.DataSource"
/>

當然,通過使用 WebSphere Application Server V7 和 WebSphere Application Server V6.1 EJB 3 Feature Pack 中的純粹 EJB 3 支持也可以獲 得注釋和 JPA 的優點。在任一種情況下,您都可以使用 JPA API 創建 EntityManagerFactory,如下所示。建議不要將此方法用於非 EJB 3 環境,因 為可能無法正確管理所創建的任何 EntityManager。但是,當您擁有 EJB 3 環 境時,可以使用此方法分離 Spring 和 JPA 配置。

<bean id="myEmf"
  class="javax.persistence.Persistence"
  factory-method="createEntityManagerFactory" >
  <constructor-arg type="java.lang.String" value="default"/> 
</bean>

IBM JDK 6

WebSphere Application Server V7 在 IBM JDK 6 上運行,由於已在此 JIRA 中作文檔說明的 Spring 問題,無法將 IBM JDK 6 與 V2.5.5 以前的 Spring 框架一起使用。

集成和管理注意事項

JMX 和 MBean

僅當 Spring JMX MBean 向 WebSphere Application Server 的容器管理器 MbeanServer 注冊後,WebSphere Application Server V6.1 和更高版本才支持 它。如果不指定任何服務器屬性,則 MBeanExporter 將嘗試自動檢測運行的 MbeanServer。因此,在 WebSphere Application Server 上運行應用程序時, Spring 框架將找到容器的 MbeanServer。

您不應使用 MBeanServerFactory 實例化 MbeanServer,然後將其注入 MbeanExporter。而且,WebSphere Application Server 不支持使用 Spring 的 ConnectorServerFactoryMBean 或 JMXConnectorServer 通過打開入站 JMX 端 口將本地 MBeanServer 公開給客戶端。

WebSphere Application Server Version 6.1 以前的版本不支持 Spring JMX Mbean。

在 WebSphere Application Server 中注冊 Spring MBean

當按下面的方式注冊時,WebSphere Application Server MBean 將由 javax.management.ObjectName 標識:

WebSphere:cell=99T73GDNode01Cell,name=JmxTestBean,node=99T73GDNode0 1,

process=server1,type=JmxTestBeanImpl

這意味著,如果它們被取消注冊,則需要使用相同的“完全限定”名稱(而 不是 MBean 的簡單名稱屬性)查找它們。最好的方法是實現 org.springframework.jmx.export.naming.ObjectNamingStrategy,它是封裝 ObjectName 實例創建的接口,並且在注冊 Bean 時,MBeanExporter 可以使用 它獲得 ObjectName。Spring Framework 論壇上提供了一個示例。可以將 ObjectNamingStrategy 實例添加到您注冊的 Bean。這可以確保在卸載應用程序 時正確地取消注冊 MBean。

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"
  lazy-init="false">
<property name="beans">
   <map> <entry key="JmxTestBean" value-ref="testBean" /> </map>
</property>
<property name="namingStrategy" ref="websphereNamingStrategy" />
...
</bean>

MBean ObjectName 和通知

由於在 WebSphere Application Server 中使用的是 MBean 的完全限定 ObjectName,因此建議您完整定義該 ObjectName 以使用通知。此 JIRA 支持改 為使用 Spring Bean 名稱,,但是僅當您在使用相應版本的 Spring 的時候, 才應該提供修復程序。

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"
  lazy-init="false">
   <property name="beans">
     <map>
      <entry key="JmxTestBean" value-ref="testBean" />
     </map>
   </property>
   <property name="namingStrategy" ref="websphereNamingStrategy" />
   <property name="notificationListenerMappings">
     <map>
      <entry key="WebSphere:cell=99T73GDNode01Cell, name=JmxTestBean,
       node=99T73GDNode01, process=server1, type=JmxTestBeanImpl">
        <bean class="client.MBeanListener" />
      </entry>
     </map>
   </property>
</bean>

System z 多調用/單調用限制

由於 Spring 不允許在 MBean 描述符中指定特定於平台的字段,因此 Spring JMX 將在 WebSphere Application Server V6.1 中的多 SR 服務器上運 行,但在部署選項中受限。WebSphere Application Server 缺省使用單調用策 略,這樣僅要求一個 MBean 實例(在一個不確定的 SR 中)就可以執行某個請 求。在某些場景中這已足夠,但是應用程序更可能需要能夠聲明多調用和單調用 方法的組合,並且可能產生聚合邏輯。

調度和線程池

Spring 提供了許多可用於調度工作的 TaskExecutor 類。只有 WebSphere Application Server 支持用於異步執行工作的 Spring TaskExecutor 才是 Spring WorkManagerTaskExecutor 類,該類可正確地利用 WebSphere Application Server 托管的線程池,並向已配置的 WorkManager 作出委托。其 他 TaskExecutor 實現可以啟動非托管線程。

在 WebSphere Application Server 管理控制台中,可以通過導航到 Resources => Asynchronous beans => Work managers 對 WorkManager 進行設置。然後可以在 Spring 配置文件中作為 workManagerName 屬性使用資 源的 JNDI 名稱來定義 WorkManagerTaskExecutor。下面的示例使用 WebSphere Application Server 的 DefaultWorkManager JNDI 名稱或 wm/default:

<bean id="myTaskExecutor"
   class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor" >
  <property name="workManagerName" value="wm/default" />
</bean>

類加載器

Spring 和 WebSphere Application Server 都使用多個開放源代碼項目,遺 憾的是,它們共有的項目版本並不總是匹配。應該將 Spring 依賴項包裝為應用 程序的一部分,並且應該按照下面的描述設置服務器以避免沖突。否則,類加載 器可能無法為運行時或應用程序加載適當的版本。通常,這將導致異常,在日志 中顯示類、ClassCastExceptions 或 java.lang.VerifyErrors 的版本不匹配。

其中一個示例是使用 Jakarta Commons Logging。要配置供應用程序使用的 Jakarta Commons Logging (JCL),或者使用不是由應用程序服務器提供的其他 版本的 JCL(例如,使用應用程序代碼嵌入的 JCL),將需要在 WebSphere Application Server 上進行專門的配置。有關如何配置已部署的應用程序,以 使用嵌入版本的常用技術的策略,請參見集成 Jakarta Commons Logging。請密 切關注支持網站,了解是否提供了有關如何在 WebSphere Application Server V6.x 產品上配置嵌入式 JCL 的更新。這僅僅是沖突的一個示例。其他示例可能 包括應用程序使用 JDOM 或特定版本的 JavaMail。不支持將 WebSphere Application Server 的 JAR 文件替換為這些或具有更高版本或不同版本的其他 包。

在 WebSphere Application Server 上困擾 Spring 用戶的另一個類加載器 問題是 Spring 加載資源的方法。資源可以包括消息綁定之類的內容,通過類加 載器層次結構和在層次結構中查找資源的各種策略,可以在非預期的位置找到使 用公共名稱的資源。可以使用 WebSphere Application Server 類加載器查看器 來幫助解決此問題。資源與其他版本的公共庫的組合可能要求應用程序將資源重 命名為唯一的名稱。

James Estes 在 Spring 論壇上闡述的示例包含打包為 EAR 文件的 EJB 項 目和 Web 項目。所描述的解決方案是將 spring.jar 文件同時添加到 WEB- INF/lib 和頂級 EAR 中,然後將 WEB 項目的類加載器策略設置為 PARENT LAST ,以便先找到 WEB-INF/lib 中的版本。EJB 項目使用 EAR 中的版本。

設計注意事項

Spring Framework 提供的某些基礎結構服務將復制由基於標准的應用程序服 務器運行時提供的服務。而且,從基礎 J2EE 應用程序服務器抽象出 Spring 框 架基礎結構必然要削弱與應用程序服務器運行時服務質量的集成,如安全性、工 作負載管理和高可用性。因此,在應用程序設計過程中,必須認真考慮部署到 WebSphere Application Server 中的應用程序中的 Spring Framework 使用, 以避免降低 WebSphere Application Server 提供的任何服務質量。如果沒有任 何其他建議,首選的方法是直接使用 WebSphere Application Server 提供的服 務,以便基於開放標准開發應用程序,並確保未來部署的靈活性。

非托管線程

某些 Spring 場景可能導致創建非托管的線程。非托管線程對 WebSphere Application Server 是未知的,並且不能訪問 Java EE 上下文信息。此外,它 們可以在 WebSphere Application Server 不知道的情況下利用資源,在管理員 無法控制其數量和資源使用的情況下存在,在發生故障時,它們還阻止應用程序 服務器正常關閉或恢復資源。應用程序應該避免導致啟動非托管線程的任何場景 ,如:

registerShutdownHook

避免使用 Spring AbstractApplicationContext 或其子類之一。 registerShutdownHook 是一個公共方法,它可以創建線程並將其注冊到 Java 虛擬機,以便在關機時運行以關閉 ApplicationContext。應用程序可以避免這 一點,方法是利用從 WebSphere 容器接收的常規生命周期通知來顯式調用 ApplicationContext 上的關閉。

WeakReferenceMonitor

Spring 為簡化開發 EJB 組件提供了方便的類,但是請注意,這些方便的類 會生成由 WeakReferenceMonitor 用來執行清除操作的非托管線程。

調度

Spring 提供(或集成)了大量的調度包,但是,只有與 WebSphere Application Server 托管的線程一起使用的 Spring 調度包才是 CommonJ WorkManager。其他包(如 quartz 和 JDK Timer)會啟動非托管線程,應該避 免使用。

使用 Hibernate

Hibernate 是用於 POJO 的開放源代碼持久性框架,它通過 XML 配置文件提 供 POJO 到關系數據庫表的對象-關系映射。Hibernate 框架是應用程序調用來 實現數據持久性的數據訪問抽象層。此外,Hibernate 還提供了從 Java 類到數 據庫表(以及從 Java 數據類型到 SQL 數據類型)的映射,以及數據查詢和檢 索功能。Hibernate 生成必需的 SQL 調用,還負責結果集處理和對象轉換。

Hibernate(如 OpenJPA)實現了 Java Persistence API (JPA) 規范,此規 范是 Java EE 5 的必備組成部分。(有關如何使用 Hibernate 的 developerWorks 文章,請參見參考資料。)

使用場景

以下場景描述了有關如何將 Hibernate 與 WebSphere Application Server 和 WebSphere 產品堆棧結合使用的一些可能場景。這些僅是示例場景,不應認 為是推薦的場景。

使用 WebSphere Application Server 數據源

為了讓 Hibernate 從 WebSphere Application Server 獲取數據庫連接,必 須使用 Java EE(以前稱為 J2EE)規范中強制規定的資源引用。這可以確保 WebSphere Application Server 能夠為連接池、事務語義和隔離級別提供正確 的行為。通過將 hibernate.connection.datasource 屬性(在 Hibernate 配置 文件中進行了定義)設置為引用在模塊的部署描述符中定義的資源引用(例如 java:comp/env/jdbc/myDSRef),將 Hibernate 配置為從 WebSphere Application Server 檢索數據源。例如:

<property name="hibernate.connection.datasource">
   java:/comp/env/jdbc/myDSRef
</property>

Web 應用程序的 Java EE 資源引用在 WAR 文件級別定義,這意味著容器中 的所有 Servlet 和 Java 類均共享資源引用。在 EJB 模塊內部,資源引用在各 個 EJB 組件上定義。這意味著,如果許多 EJB 組件都使用相同的 Hibernate 配置,則每個 EJB 必須在每個 EJB 組件上定義相同的引用名稱。這會導致復雜 化,稍後我們將對此做進一步討論。

配置了數據源之後,確保 Hibernate 正常工作的下一個步驟是正確配置事務 支持。

事務策略配置

為了正確地運行事務,Hibernate 需要兩個重要部分的配置。第一個部分是 hibernate.transaction.factory_class,它定義事務控制,第二個部分是 hibernate.transaction.manager_lookup_class,它定義注冊事務同步的機制, 這樣,當持久性管理器需要與數據庫同步更改時,將會在事務端得到通知。對於 事務控制,同時支持容器管理的配置和 Bean 管理的配置。將 Hibernate 和 WebSphere Application Server 結合使用時,必須在 Hibernate.cfg.xml 中設 置以下屬性:

對於容器管理的事務:

<property name="hibernate.transaction.factory_class">
   org.hibernate.transaction.CMTTransactionFactory
</property>
<property name="hibernate.transaction.manager_lookup_class">
   org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
</property>

對於 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 >

jta.UserTransaction 屬性將工廠類配置為從 WebSphere 容器獲取 UserTransaction 對象實例的實例。

WebSphere Application Server V6.x 和更高版本在 WebSphere 平台上支持 hibernate.transaction.manager_lookup_class 屬性,WebSphere Business Integration Server Foundation V5.1 和更高版本也支持此屬性。此屬性將 Hibernate 配置為使用在 WebSphere Business Integration Server Foundation V5.1 和 WebSphere Application Server V6.0 中引入的 ExtendedJTATransaction 接口。WebSphere ExtendedJTATransaction 接口建立 了一種在 Java EE 5 中通過 JTA 1.1 規范正式確立的模式。

不支持的事務配置

Hibernate 文檔描述了用於在 WebSphere Application Server 版本 4 和 5 產品上運行的事務策略配置,但是這些配置使用內部 WebSphere 接口,在早期 版本上不受支持。上面僅描述了受支持的 Hibernate 事務配置,如前面所述, 這意味著僅在 WebSphere Business Integration Server Foundation V5.1 和 WebSphere Application Server Version 6.x 以及更高版本上支持使用 Hibernate。

WebSphere Application Server 環境中的 Hibernate 使用模式

當結合使用 Hibernate 和 WebSphere Application Server 時,Hibernate 的“按請求會話”和“長時間對話”模式均可使用。客戶必須選擇適用於其應用 程序的模式,不過我們主張使用“按請求會話”模式,因為它可以提供更好的可 擴展性。

多個隔離級別

可共享的連接通過讓多個資源用戶能夠共享現有的連接,在 WebSphere Application Server 中提供了性能改進。不過,如果可共享的連接和多個隔離 級別都是必需的,則為每個連接配置定義單獨的資源引用和 Hibernate 會話工 廠。不能夠更改共享連接的隔離級別。因此,也不可能使用 hibernate.connection.isolation 屬性在可共享的連接上設置隔離級別。有關 連接共享的策略和約束的詳細信息,請參見在 WebSphere Application Server V5 中共享連接。(盡管本文一般適合於在 WebSphere Application Server V5 上使用的所有共享連接,但是連接共享建議仍適用於在 V6.x 上運行的 Hibernate。)

Web 應用程序

可以在 HttpSession 對象中使用和存儲 Hibernate 的“長時間對話”會話 ;不過,Hibernate 會話持有活動實例,由於可能需要將會話序列化或將其復制 到其他集群成員,因此將其存儲在 HttpSession 中不是可擴展的模式。最好使 用 HttpSession 來存儲斷開連接的對象(只要它們非常小,即 10KB 到 50KB) ,並且在需要更新時,重新將它們與新的 Hibernate 會話關聯起來。這是因為 HttpSession 最適用於書簽,而不適用於緩存。在使用智能序列化改進 HttpSession 性能中討論了如何使 HttpSession 的內存使用率降至最低。與將 HttpSession 用作緩存不同,應該考慮使用 ObjectGrid 或 DistributedObjectCache 之類的 WebSphere 數據緩存技術,這在下一部分進行 介紹。

有關高性能、可擴展應用程序的最佳實踐,強烈建議您閱讀 Performance Analysis for Java Websites 一書。

在本文發表之際,Hibernate 的識別集群的緩存與 WebSphere Application Server 相結合的行為還沒有確定,因此,還不能確定是否支持使用該緩存,我 們對此不做進一步的討論。因此,需要分布式緩存的客戶應當考慮創建使用屬性 hibernate.cache.provider_class 實現 org.hibernate.cache.CacheProvider 的類,該屬性將采用 WebSphere 中的兩個分布式緩存實現中的一個。

集成二級緩存

Hibernate 會話表示工作單元的范圍。在 Hibernate 會話的生命周期中, Session 接口管理持久性。通常,它通過保留對單個線程有效的一級緩存實例, 維護它負責的映射實體類實例的可識別性或狀態,從而做到這一點。該緩存在工 作單元(會話)完成時消失。還可以將二級緩存配置為在 SessionFactory 的所 有會話之間共享(包括在集群之間共享)。請注意,在 Hibernate 中進行緩存 會導致一些需要解決的問題。第一,對於數據庫的外部更改或跨集群更改,無法 確保緩存的一致性(除非使用識別集群的緩存)。第二,其他層(如數據庫)可 能已經緩存,從而使 Hibernate 緩存的價值降至最低。在進行應用程序設計時 ,必須認真考慮這些問題,但是這些問題超出了本文的討論范圍。

Hibernate 附帶了幾個預配置的緩存。在 Hibernate 緩存文檔頁中可以找到 關於這些緩存的信息。對於只讀數據,一個內存緩存可能就足夠了。不過,當對 應用程序進行集群並需要識別集群的緩存時,本地只讀緩存是不夠的。如果需要 分布式緩存,我們建議使用 WebSphere 提供的分布式緩存實現之一。可以將它 們用作 Hibernate 的二級緩存:

DistributedMap/DistributedObjectCache 接口提供了支持 WebSphere v6.x 產品系列的分布式緩存。有關詳細信息,請參見將 DistributedMap 和 DistributedObjectCache 接口用於動態緩存。

作為 WebSphere Extended Deployment 產品一部分的 ObjectGrid 提供可擴 展的對象緩存支持。有關詳細信息,請參見 ObjectGrid。

在 WebSphere Enterprise Service Bus 和 WebSphere Process Server 中 使用 Hibernate

WebSphere Process Server 和 WebSphere Enterprise Service Bus (ESB) 將 Service Component Architecture (SCA) 和 Service Data Objects (SDO) 用作 SOA 的組裝和編程模型。(請參見參考資料,了解關於 SCA 和 SDO 的更 多信息。)SCA 組件不是 Java EE 組件,因此它們沒有資源引用,而是依靠服 務和適配器來連接系統。在構建 Java SCA 組件時,不能使用資源引用;因此, SCA 組件不能直接使用 Hibernate。

在這種情況下,應將 Hibernate 持久性隱藏在某種 Facade 後面。有兩個替 代方案:

創建本地 EJB 會話 Facade 以包裝 Hibernate 持久性。會話 Facade 提供 適配器邏輯,以便將 Hibernate 實體 POJO 映射到服務數據對象,以及進行反 向映射。然後集成開發人員可以使用 EJB 導入來調用會話 Facade,並以緊密耦 合方式使用對應的服務質量 (QoS) 調用它。

創建 EJB Web 服務會話 Facade 以包裝 Hibernate 持久性。然後集成開發 人員可以使用 Web 服務導入調用實現持久性的 Web 服務。這不需要構建 POJO 到 SDO 的轉換程序,因為目前 SCA 對數據類型只使用 SDO。圖 1 說明了使用 兩種模式的業務流程,但該流程的詳細信息不在本文的討論范圍之內。

圖 1. 示例業務流程

WebSphere Application Server V6.1 上的 Hibernate JPA API

Hibernate 的 JPA 支持提供 JPA 標准持久性,並且是專有 Hibernate API 的較好替代方案。Hibernate 的 JPA 實現需要基於 Java SE 5 的運行時,因此 僅在 WebSphere Application Server V6.1 或更高版本上運行。在本文發表之 際,Hibernate 的 JPA 支持不能在 WebSphere System z 和 iSeries 平台上運 行。Hibernate 文檔描述了如何使用 Hibernate 的 JPA 實現包裝和部署應用程 序。

不可交互操作/不可移植的功能

JPA 規范中的 3.2.4.2 部分描述了可能導致互操作性和潛在的可移植性問題 的情況。這與結合使用延遲加載(即 @Basic(fetch=LAZY))和分離對象有關。 將分離對象合並回會話時,JPA 將檢查該對象,並使用任何更改值來更新數據存 儲區。不過,數據對象是簡單的 POJO。在分離時,如果部分 POJO 狀態沒有加 載,則在合並回去時可能顯示為已更改。要使它正常工作,供應商必須實現特定 於其運行時的序列化技術。這不是可互操作的,語義也可能不是可移植的。

產品和客戶技術支持

用戶合理關注的領域是對使用開放源代碼的項目的支持,以及使用開放源代 碼對供應商支持其許可產品的影響。IBM 了解某些客戶可能希望將非 IBM 的框 架和 IBM WebSphere Application Server 結合使用,並且在為客戶提供一些信 息,以促進他們為 IBM WebSphere Application Server 創建最可靠的操作環境 。IBM 考慮了客戶安裝的開放源代碼和應用程序框架,它們或者打包為應用程序 的一部分,或者作為共享庫成為應用程序代碼的一部分。在使用開放源代碼項目 時通過謹慎地利用此信息,客戶可以滿懷信心地使用 IBM 產品,並繼續訪問 IBM 產品和技術支持。如果在將這些框架與 WebSphere 產品結合使用時遇到問 題,IBM 將盡力確保 WebSphere 產品不出現問題。

如果客戶認真研究了本文中的建議,並理解以下幾個關鍵點,則預期可以安 全地在 IBM 產品上使用 Spring 和 Hibernate 之類的框架:

客戶必須確保按 WebSphere Application Server 允許的方式使用這些框架 。具體來說,這意味著客戶在使用內部產品接口時,不應使用框架——遺憾的是 ,許多開放源代碼框架在未經認真配置的情況下就這樣使用了。客戶應避免在 WebSphere 上明確記錄應避免的場景。

對於開放源代碼框架,客戶應該確保理解並能夠訪問與 WebSphere Application Server 一起使用的框架的匹配源代碼和二進制代碼。

建議客戶從開放源代碼社區或與開放源代碼社區合作的合作伙伴那裡獲取框 架的補救性服務。

有關 IBM 支持和策略的詳細信息,請參考 IBM 支持手冊和 WebSphere Application Server 支持聲明。

盡管在開放源代碼環境中使用 WebSphere Application Servers 時按照本文 建議的做法有助於增強您的體驗,但本文並沒有列出開放源代碼組件影響 WebSphere Application Server 操作或其他組件操作的所有情況。使用開放源 代碼的用戶務必檢查所有組件的規范,以避免出現許可、支持和技術問題。

本文中的術語“支持”或“受支持”指示描述的用法僅限於使用 IBM 有文檔 記錄的功能。作者盡最大努力提供關於如何配置和使用這些框架的建議,以確保 其用法與有文檔記錄的產品行為一致,但本文不是保證,也不是 Spring 或 Hibernate 的支持聲明。

結束語

Spring Framework 正在迅速普及。開發人員喜歡使用易用的接口和基於 XML 的配置加速 J2EE 開發和輕松地進行單元測試。框架本身也正在迅速發展,現在 ,網站上列出了許多子項目。與使用所有軟件一樣,確定在應用程序中使用它可 以提供什麼好處,以及是否具有實現相同結果的更好替代方法是非常重要的。當 然,Spring 中的一些功能復制了已嵌入 WebSphere Application Server 的功 能,所以將署到該服務器中的應用程序使用此額外的框架代碼層是不可取的。但 是,如果使用得當,您可以將 Spring 的許多易用的開發功能與 WebSphere Application Server 可靠的集成企業支持功能結合使用,以快速開發企業應用 程序,並將其部署到 IBM 中行業領先的 J2EE 應用程序服務器。

Hibernate 是可以與 WebSphere Application Server 一起成功使用的多個 持久性框架之一,可以提供到關系數據庫中存儲的實體數據的對象-關系映射( 前提是足夠小心地避免有問題的場景)。特別是,您必須確保使用 Hibernate 不涉及使用內部 WebSphere Application Server 接口。按照這裡提供的建議, 您可以避免一些常見問題,並將 Hibernate 用作部署到 WebSphere Application Server 的應用程序的持久性框架。

致謝

作者要感謝 Keys Botzum、Paul Glezen、Thomas Sandwick、Bob Conyers、 Neil Laraway 和 Lucas Partridge,他們對本文提出了寶貴意見並作出了貢獻 。

作者簡介

Roland Barcia 是 IBM Software Services for WebSphere 的 IT 咨詢專家 。他是 IBM WebSphere:Deployment and Advanced Configuration 一書的合著 者。

Jim Knutson 是 WebSphere 的 J2EE 架構師。Jim 負責 IBM 參與的 J2EE 相關規范,他參與這些工作的時間可追溯到 J2EE 出現以前。Jim 還參與了編程 模型的改進,以支持 SOA 和 Web 服務。

Sara Mitchell 在位於英國的 IBM Hursley 開發實驗室工作,是 WebSphere Application Server 團隊的負責人。

Tim Ward 是 IBM Hursley lab 的一名軟件工程師。他積極從事敏捷項目, 並且是 WebSphere Application Server 的開發人員之一。Tim 擁有英國劍橋大 學理論物理學專業的理學碩士學位。

Tom Alcott 是 IBM 美國的一位 IT 咨詢專家。自 1998 年 Worldwide WebSphere Technical Sales Support 小組成立以來,他就一直是該小組的成員 。在此期間,他花費了大部分時間來編寫用戶手冊。在開始研究 WebSphere 之 前,他是 IBM 的 Transarc 實驗室的一名系統工程師,負責支持 TXSeries。他 有 20 多年從事基於大型機和分布式系統的應用程序設計與開發工作的背景。他 撰寫並發表了大量關於 WebSphere 運行時問題的文章。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved