Spring+EJB


最近暇で、普段のプロジェクトの開発とEJB 2.xの使用過程でもたらした様々な不便を結びつけて、Springと結びつけてEJBの開発と呼び出しの方面の技術を深く総括して研究することを決定して、主に3つの方面を含みます:
 
1、取引制御
Struts 2+EJB 2+Spring 2+Ibatisのテクノロジーアーキテクチャでは、トランザクション制御を行う3つの場所があります.
1)EJB 2によるグローバルトランザクション制御.EJBのトランザクション制御は、コンテナ管理トランザクションとBean管理トランザクションの2種類に分けられる.
EJBコンテナを使用してトランザクションを管理する場合、デフォルトではJTAトランザクションが有効になり、EJBメソッドに基づくトランザクション制御です.EJBメソッドには、ビジネスを完了し、トランザクション制御を行う必要があるさまざまなアクションが含まれており、下に完全なインスタンスが表示されます.
例1(ejbコンテナによってトランザクションを完全に管理する):
SpringのアプリケーションContext.xmlファイル構成:
<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<!--     JNDI   -->
	<bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
		<property name="jndiName" value="xpDS" />
		<property name="jndiEnvironment">
			<props>
				<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
				<prop key="java.naming.provider.url">t3://127.0.0.1:7001</prop>
				<prop key="java.naming.security.principal">weblogic</prop>
				<prop key="java.naming.security.credentials">weblogic</prop>
			</props>
		</property>
	</bean>
                <!-- ibatis sqlMapClient -->
	<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
		<property name="configLocation" value="classpath:sql-map-config.xml"/>
		<property name="dataSource" ref="jndiDataSource"/>
	</bean>
                <!--   bo     -->
	<import resource="classpath:/config/dmtab.xml" />
</beans>

 
 
SpringのアプリケーションContext.xmlファイルでは、トランザクション管理に関する設定は行われていません.
 
EJBメソッドコード:
public class HelloBean implements javax.ejb.SessionBean {

...

                public String saveDM_DWLX(DM_DWLX param) {
		DM_DWLX temp = new DM_DWLX();
		temp.setDWLX_DM("89");
		temp.setDWLX_MC("    ");
		boDM_DWLX.insertDM_DWLX(temp);//           
		boDM_DWLX.insertDM_DWLX(param);//        
		return null;
	}

...

}

 注意:ここでの2回の挿入操作はejbメソッドで行われ、この2回の挿入操作をboDM_に移植するとDWLX.insertDM_DWLX(DM_DWLX param)メソッドで完了すると、トランザクションは正常にロールバックされません.したがって、ejbによってトランザクションを制御する場合、ejbメソッドはビジネスメソッドとなり、1つのビジネスに対応する様々な操作がカプセル化され、プロジェクト技術アーキテクチャでejbをfacadeとして使用することと分散型のアプリケーションを実現することとは異なり、また、ビジネスが変化するたびにEJBを修正する必要があり、システムの修正に大きな不便をもたらす.
 
ejb-jar.xmlファイル構成:
<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar id="ejb-jar_1" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1">

   <description</description>
   <display-name>EJBTest</display-name>

   <enterprise-beans>      
      <!-- Session Beans -->
      <session id="Session_Hello">
         <description><![CDATA[An EJB named Hello]]></description>
         <display-name>Hello</display-name>

         <ejb-name>Hello</ejb-name>

         <home>net.xp.service.ejb.HelloHome</home>
         <remote>net.xp.service.ejb.Hello</remote>
         <local-home>net.xp.service.ejb.HelloLocalHome</local-home>
         <local>net.xp.service.ejb.HelloLocal</local>
         <ejb-class>net.xp.service.ejb.HelloBean</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type><!--  :            -->

      </session>
   </enterprise-beans>
   <container-transaction><!--        (   ,         )-->
      <description></description>
      <method>
        <description></description>
        <ejb-name>Hello</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
   </container-transaction>
   ...

</ejb-jar>

 
クライアントテストコード:
public static void main(String[] args) throws Exception {
		Properties p = new Properties();
		p.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
		p.put("java.naming.provider.url","t3://127.0.0.1:7001");
		InitialContext ctx = new InitialContext(p);
		Object obj = ctx.lookup("Hello");
		HelloHome home = (HelloHome)PortableRemoteObject.narrow(obj, HelloHome.class);
		Hello hello = home.create();
		
		DM_DWLX model = new DM_DWLX();
		model.setDWLX_DM("AAa");//          
		model.setDWLX_MC("AA");
		hello.saveDM_DWLX(model);
}

 
テスト結果:
ejbメソッドsaveDM_DWLXでは、1回目の挿入操作は成功したが、2回目の挿入操作が失敗した場合、トランザクションは正常にロールバックされる
 
2)Spring 2の宣言トランザクションによるビジネス・レベルでのトランザクション制御
Springは、プログラミングトランザクションと宣言トランザクションの2つのトランザクション管理方法を提供します.ここでは、主に宣言トランザクションを使用する構成を記録します.
 
Spring宣言トランザクション構成コード:
<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<!--     JNDI   -->
	<bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
		<property name="jndiName" value="ds" />
		<property name="jndiEnvironment">
			<props>
				<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
				<prop key="java.naming.provider.url">t3://127.0.0.1:7001</prop>
				<prop key="java.naming.security.principal">weblogic</prop>
				<prop key="java.naming.security.credentials">weblogic</prop>
			</props>
		</property>
	</bean>
	 
	<!-- ibatis sqlMapClient -->
	<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
		<property name="configLocation" value="classpath:sql-map-config.xml"/>
		<property name="dataSource" ref="jndiDataSource"/>
	</bean>
	<!--       -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="jndiDataSource"/>
	</bean>
                <!--jta     ,           ,  jta  ,     jndi datasource   XA DataSource
                <bean id="transactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager">
	</bean>
	
	-->
                <!--aop  ,       bo               -->
	<aop:config>
		<aop:pointcut id="defaultServiceOperation" expression="execution(* net.xp.service.bo..*.*(..))"/>
		<aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>
	</aop:config>
    <!--    ,            -->	
    <tx:advice id="defaultTxAdvice" transaction-manager="transactionManager">-->
	<!-- <tx:advice id="defaultTxAdvice">
        <tx:attributes>
            <tx:method name="get*" read-only="true" rollback-for="Exception"/>
            <tx:method name="select*" read-only="true" rollback-for="Exception"/>
            <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="make*" propagation="REQUIRED" rollback-for="Exception"/>
        </tx:attributes>
    </tx:advice>
	
	
	<!--   bo     -->
	<import resource="classpath:/config/dmtab.xml" />
</beans>

 
この構成を使用すると、トランザクションはboレイヤで制御され、ビジネスレイヤでのトランザクション制御の要件に合致し、構成と適用が簡単になります.このスキームを使用してプロジェクト内のトランザクション制御を推奨します.
 
3)IBatisによるDAO層のトランザクションの制御
 
2.Springに基づくEJB開発
SpringはEJBの実装を支援するクラスを多く提供していますが、実装すると面倒です.Springの公式ドキュメントの翻訳後の文字を参照してください.
 
「Spring方式を使用しないEJBクライアントと比較して、SpringのEJBクライアントには追加のメリットがあります.通常、ローカルとリモートのEJB呼び出しの間でEJBクライアントコードを自由に切り替えることができるようにするには、問題が発生します.これは、リモートインタフェースの方法で、彼らが投げ出したRemoteExceptionメソッドを明らかにし、クライアントコードがこのような異常を処理しなければならないためです.ローカル・インタフェースのアプローチは不要です.ローカルEJBに対するコードをリモートEJBへのアクセスに変更するには、クライアント・コードを変更し、リモート・例外を処理するコードを追加する必要があります.逆に、使用できないリモート・例外処理コードを保持するか、これらの例外処理コードを除去するために変更する必要があります.SpringのリモートEJBエージェントを使用すると、不要になりますビジネス・メソッド・インタフェースおよびEJBのインプリメンテーション・コードにおいて、投げ出すRemoteExceptionを宣言するのではなく、似たようなリモート・インタフェースを定義します.唯一の違いは、RemoteExceptionが投げ出された後、エージェント・オブジェクトに渡して動的に調整する2つのインタフェースです.つまり、クライアント・コードはRemoteExceptionというchecked exceptionと付き合う必要はありません.実際にはEJB呼び出しで投げ出されますRemoteExceptionRemoteAccessExceptionのサブクラスであるunchecked exception RuntimeExceptionで再放出されます.これにより、ターゲット・サービスはローカルEJBまたはリモートEJB(さらにはPOJO)で使用できます.間を任意に切り替えると、クライアントはこのような切り替えに関心を持つ必要はありません.もちろん、これらはオプションであり、ビジネスインタフェースでRemoteExceptionsの異常を宣言することを阻止するものはありません.」
 
最初はこの文字を見ていて確かに久しぶりに興奮しましたが、コードを書く実践を経て、まったくそうではないことに気づきました.ローカルEJBを実現するときはクライアントは確かに異常をキャプチャする必要はありませんが、リモートEJBを実現するときはクライアントはRemoteExceptionをキャプチャし、公式ドキュメントにはローカルEJB呼び出しのコードの一部しか提供されていません.リモートEJB呼び出しのコードを提供していないので、急にだまされたような感じがして、ネット上で多くの文章を探して、聞いただけで、答えがあるのを見ていないので、本当に理解できません~~
 
もし誰かが知っていたら、私に返事をして、あなたの理解を分かち合って、ここで先に感謝します.
 
 
3、EJBローカルインタフェースとリモートインタフェース呼び出し
 
 EJBリモートインタフェース呼び出しは言わないで、主にEJBローカルインタフェース呼び出しについて話しましょう.以前はプロジェクトでリモートインタフェース呼び出しを使っていましたが、ローカルインタフェース呼び出しを使ったことがありません.簡単だと思って、勝手にコードテストを書いてみました.試してみませんでしたが、びっくりして、鼻の灰にぶつかって、NameNotFoundExceptionに報告していました.最終的にEJBローカルインタフェースを呼び出すサーブレットとejbをEARパッケージにパッケージ化してテストに成功しましたが、なぜwebとejbをwarとjarでWebLogicの同じdomainの下に配置すればだめなのか理解できませんでした.ほほほ、親切な高人の解答を待たなければなりません~~
1篇の関連する文章を推薦します 参考までに