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.
  • ではなく、必ずパラメトリック関数があるかどうかを確認しなければならない.
  • セッションbeanは、他のセッション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サービスにすることができます.唯一しなければならないのはinterfaceに@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に返信することを覚えておいてください.(EJB3 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 destroyになるまで、clientにstateful session beanを持たせることです.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 Servicesはもともと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はinterfaceに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に注意して効率が悪くなる.