EJB3 - Session bean

11986 ワード

EJB3 - Session bean


EJB3 - Session bean

description

実はsession beanは最初から見ていたので、振り返ってみるとお菓子が浮いていることに重点を置いています.

reference

EJB3 in Action - CH3 - Building business logic with session beans

Focal Points

  • session beanは必ず1つ以上のinterfaceと1つの実現
  • を持っていなければならない.
  • の1つのセッションbeanは複数のinterfaceを持つことができるので、クライアントが@Localのinterfaceを呼び出すと、localのセッションbeanが使用される.@Remoteまたは@WebServiceを使用するのはremoteまたはwebサービスを使用するセッションbeanです.
  • session beanはconcrete classでなければならない.abstractやfinalではない.
  • session beanは、他のsession beanまたはPOJOのsubclassであるもよい.
  • session beanのビジネスmethodとlifecycle callbackはsuper classまたはsession bean classに決定することができる.
  • session beanのannotationの継承には条件があります.class levelです.例えば@Stateless、@Statefulは無視されますが、lifecycle callbackは継承されます.
  • セッションbeanのビジネスメソッドnameはejbで始まることはできません.例えばejbDoit()
  • ではありません.
  • セッションbeanのmethodはpublicであり、staticまたはfinal
  • ではない必要があります.
  • remoteビジネスインターフェースを使用するargumentとreturn typeはSerizable
  • として実装する必要があります.
  • すべてのセッションbeanのライフサイクルはcreation/destruction
  • です.
  • stateful beanはstateless beanよりpassivation/activation
  • 多い
  • stateless beanのlifecycle callbackは@PostConstruct,@PreDestroy
  • stateful beanのlifecycle callbackは@PostConstruct,@PreDestroy,@PostActivate,@PrePassivate
  • @PostConstruct,@PreDestroyは比較的簡単である.containerがセッションbeanをインスタンス化して@PostContructを呼び出し、containerがセッションbeanを除去する前に@PreDestroy
  • を呼び出す
  • @PostActivate,@PrePassivateは比較的特別である.containerがstateful beanが停止したと判断し、このsession beanを一時的に無効にすることを決定すると、この動作は不動態化と呼ばれます.containerは失効したstateful beanを再び有効にすることをアクティブにします.したがって@PostActivateはactivation後に呼び出されるmethodであり,@PrePassivateは不動態化前に呼び出されるmethodである.
  • lifecycle callbackはpublic,private,protected,package-protected
  • であってもよい
  • lifecycle callbackは主にsession beanのためにインスタンス化後に必要なリソースとcontainerから除去する前に解放するリソースを準備するために使用される.
  • lifecycle callbackはsession bean以外にも別々のinterceptor class
  • に置くことができる.
  • stateless session beanにはpoolがあり、つまり一定数のstateless session beanがcontainerのpoolの中で
  • である.
  • @Statelessの定義
  • 属性にはname,mappedName,description
  • があります.
  • name属性はbeanのnameを指定するために用いられ、あるcontainerはJNDIとバインドするために用いる.nameが設定されていなければbeanのclass nameになります.
  • mappedNameはvender-specific(メーカー固有)である、すなわちcontainerによって異なる場合がある.GlassFishではmappedNameの値をJNDI nameにバインドする.

  • @Local:stateless session beanのlocal interface、local interfaceはこのsession beanとclientが同じJVM上で実行することを示す.
  • @Remote:クライアントがcontainer以外のJVMに存在する場合は@Remoteを使用する必要があります
  • @Remote interfaceはjavaを継承することができる.rmi.Remote
     public interface TestRemote extends Remote { ... } 
    プログラムにRemoteを継承すると書かれていなくてもcontainerはbyte code段階でRemoteを継承する動作
  • を挿入する.
  • プログラム上でjavaを継承する.rmi.Remoteのメリットはjavaを処理しないことです.rmi.RemoteException
  • @Remoteビジネスインターフェースには、RMI
  • を通過するには、すべてのパラメータとエコー値がSerializableである必要があります.
  • @WebServices:@WebServicesを介してセッションbeanをSOAP-based web serviceにすることができる.唯一やるべきことはインターネットに@WebServicesを加えることです.
  • ビジネスインターフェースを同時に@Localまた@Remoteまたはまた@WebServiceにすることはできませんが、インターフェースの継承を通して使用する@Remote session beanか@Localのsession beanかを変更できます.
  • session beanを置くlifecycle callback
  • @PostConstruct,@PreDestroyは複数あります(ただし、セッションbeanを1つ試してみるとlifecycle callbackが1つしか有効ではありません.せいぜいcallback以外にinterceptorを指定し、interceptorのlifecycle callbackが1つ有効です.)
  • lifecycle callback pattern:void()
  • に適合する
  • interceptor内のlifecycle callbackはpattern:Object(InvocationContext)throws Exceptionに適合し、InvocationContextに返信することを覚えておいてください.proceed、実行を継続しないつもりがない限り.(EJB 3 Interceptor参照)
  • session beanのlifecycle callbackはchecked exceptionがあってはならず、interceptorのものは可能である.
  • セッションbeanのlifecycle callbackには入力パラメータがありません.interceptorはInvocationContextに入力します.そうでない場合javaがあります.lang.IllegalArgumentException: wrong number of arguments
  • stateless session beanとstateful session beanの違いは主にcontainer管理の方式にあり、stateless session beanは開始後にcontainerにpoolに入れられ、clientが使用するときにpoolから取り出し、使い終わったらpoolに戻す.stateful session beanは、clientが離れるまでstateful session beanを1つのclientに持たせる.stateful session beanとclientはone to oneの関係です.
  • stateful session beanは代価を払う必要があり、stateless session beanはすべてのclient共用session beanが比較的資源を節約できるため、stateful session beanはclientとone to oneの関係で資源を消費する.containerが消費するリソースが多すぎると判断するとpassivateの動作が開始する.
  • stateful session beanはリソースを消費するため、stateful session beanに@Remove methodを加えることに注意し、このmethodを呼び出すとcontainerはこのmethod destroyを担当してリソースを節約する.
  • stateful session beanはpassivateの時にserializeの動作をするので、stateful session beanのclassメンバーはSerializableを実際にしなければならないか、元のタイプでなければならないことに注意する.そうでない場合、passivateの場合、例えば[NRU-stateful.SimpleStatefulBean]:passivateEJB()、Exception caughtのexceptionが現れるのは、そのobjectをserializeできないためである.serializeを必要としないclassメンバーを使用する場合はtransientでそのclassメンバーを宣言するか@PrePassivateでclassメンバーをnullに変更し@PostActivateで設定すればよい.
  • stateful session beanを使用する方法はほとんどstateless session beanの方法とほぼ同じであり、唯一異なるのはstateful session beanのビジネスインターフェースが@Localと@Remoteしか使用できず@WebServicesは使用できないことである.SOAP-based web Serviceはそもそもstatefulではないので使えません.
  • stateful session beanのライフサイクルにおいて重要な点はcontainerがdestroyのpassivateの時にstateful session beanを先にactivateしてからpassivateすることである.
    @Stateful(name="SimpleStatefulBean", mappedName="ejb/SimpleStatefulBean")
    public class SimpleStatefulBean implements SimpleStatefulRemote {
    private Logger logger = Logger.getLogger("SimpleStatefulBean");
    private byte[] b = new byte[100000];
    {
    for ( int i = 0; i < b.length; i++ ) {
    b[i] = (byte) 100;
    }
    }
    public String simpleShow() {
    return this + ":This is simple show" + b;
    }
    @PostConstruct
    public void postConstruct() {
    logger.info("create " + this);
    }
    @PreDestroy
    public void preDestroy() {
    logger.info("destroy " + this);
    }
    @PostActivate
    public void postActivate() {
    logger.info("activate " + this);
    }
    @PrePassivate
    public void prePassivate() {
    logger.info("passivate " + this);
    }
    @Remove
    public void remove() {
    logger.info("remove " + this);
    }
    }
    
    interceptorのlifecycle callback
    @Stateless
    @Interceptors(value={SimpleInterceptor.class})
    public class SimpleStatelessBean implements SimpleStatelessLocal {
    private Logger logger = Logger.getLogger("SimpleStatelessBean");
    @Resource(name="TestQueueConnectionFactory")
    private ConnectionFactory connectionFactory;
    @Resource(name="jms/TestQueueDestination")
    private Destination destination;
    public String simpleShow() {
    try {
    Connection conn = connectionFactory.createConnection();
    Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    MessageProducer messageProducer = session.createProducer(destination);
    TextMessage message = session.createTextMessage();
    message.setText("This is text message");
    messageProducer.send(message);
    messageProducer.close();
    session.close();
    conn.close();
    } catch (JMSException ex) {
    throw new RuntimeException( ex );
    }
    return this + ":This is simple show";
    }
    }
    public class SimpleInterceptor {
    Logger logger = Logger.getLogger("SimpleStatefulBeanInterceptor");
    @PostConstruct
    public void onCreate(InvocationContext ic) {
    try {
    logger.info("create " + this);
    ic.proceed();
    } catch (Exception ex) {
    Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex);
    }
    }
    @AroundInvoke
    public Object aroundInvoke(InvocationContext ctx) throws Exception {
    logger.info(ctx + " is invoked.");
    return ctx.proceed();
    }
    @PreDestroy
    public void onDestroy(InvocationContext ic) {
    try {
    logger.info("destroy " + this);
    ic.proceed();
    } catch (Exception ex) {
    Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex);
    }
    }
    }
    
    stateful beanの@PrePassivate、@PostActivvateはinterceptor
    @Interceptors(value={SimpleInterceptor.class})
    @Stateful(name="SimpleStatefulBean", mappedName="ejb/SimpleStatefulBean") public class SimpleStatefulBean implements SimpleStatefulRemote { private byte[] b = new byte[100000]; { for ( int i = 0; i < b.length; i++ ) { b[i] = (byte) 100; } } public String simpleShow() { return this + ":This is simple show" + b; } @Remove public void remove() { Logger.getLogger("SimpleStatefulBean").info("remove " + this); } } public class SimpleInterceptor { @PostConstruct public void onCreate(InvocationContext ic) { try { Logger.getLogger(SimpleInterceptor.class.getName()).info("create " + this); ic.proceed(); } catch (Exception ex) { Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex); } } @PostActivate public void onActivate(InvocationContext ic) { try { Logger.getLogger(SimpleInterceptor.class.getName()).info("activate " + this); ic.proceed(); } catch (Exception ex) { Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex); } } @PrePassivate public void onPassivate(InvocationContext ic) { try { Logger.getLogger(SimpleInterceptor.class.getName()).info("passivate " + this); ic.proceed(); } catch (Exception ex) { Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex); } } @AroundInvoke public Object aroundInvoke(InvocationContext ctx) throws Exception { Logger.getLogger(SimpleInterceptor.class.getName()).info(ctx + " is invoked."); return ctx.proceed(); } @PreDestroy public void onDestroy(InvocationContext ic) { try { Logger.getLogger(SimpleInterceptor.class.getName()).info("destroy " + this); ic.proceed(); } catch (Exception ex) { Logger.getLogger(SimpleInterceptor.class.getName()).log(Level.SEVERE, null, ex); } } }
  • を置くこともできます
  • @EJBはセッションbeanをclient codeに注入するために使用される.@EJBにはいくつかの属性があります:name,beanInterface,beanName.nameはJNDI nameを指定するために使用され、beanNameは1つのインターフェースに2つの実作がある場合にどの実作を注入するかを決定するために使用される.
  • @EJB注入を用いる場合はJNDI nameが指定されていなければcontainerはinterface nameをJNDI name注入とする.
  • 同じinterfaceの異なる実作を注入する場合は、指定JNDI nameまたはbeanName
    @Stateless(name="SimpleStatelessBean1")
    public class SimpleStatelessBean1 implements SimpleStatelessLocal { ... }
    @Stateless(name="SimpleStatelessBean2")
    public class SimpleStatelessBean2 implements SimpleStatelessLocal { ... }
    public class SimpleStatelessServlet extends HttpServlet {
    @EJB(beanName="SimpleStatelessBean1")
    private SimpleStatelessLocal simpleStatelessLocal1;
    @EJB(beanName="SimpleStatelessBean2")
    private SimpleStatelessLocal simpleStatelessLocal2;
    ...
    }
    
  • を介して
  • はstateless beanまたはstateful beanを他のstateful beanに注入することができる.しかしstateful beanをstateless beanに注入することはできない.stateful session beanはすべてのclientに共有されるからだ.
  • stateful beanを別のstateful beanに注入すると、注入されたstateful bean destroyを持つと、持たれたstateful beanも一緒にdestroy.
  • stateful beanを用いる状態をDBに置くかserver sideのファイルに置くかHttpSessionを置くことができるが、不要なリソースをクリアすることに注意する.
  • conversation stateを格納ときは、primitiveなどの格納値が小さいほどよいことに注意する.
  • stateful bean@Remove methodを定義することを覚えておいてください.
  • serverからstateful beanの効率が最も良い状態に調整し、頻繁なpassivate/activateに注意して効率が悪くなることが多い.