`
wayne446
  • 浏览: 28660 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

EJB3 Session bean

    博客分类:
  • j2ee
阅读更多

EJB3 - Session bean

 

description

其實session bean是最一開始就看的, 回過頭來看再記重點有點心浮氣躁.

reference

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

Focal Points

  • session bean一定要有一個以上的interface與一個實現
  • 一個session bean可以有多個interface, 所以當客戶端調用一個@Local的interface, 就是使用local的session bean. 使用@Remote或@WebService就是用remote或web service的session bean.
  • session bean一定要是concrete class, 一定要有無參构造函数, 不能是abstract或final.
  • session bean可以是其他session bean或POJO的subclass.
  • session bean的business method與lifecycle callback可定在super class或session bean class裡.
  • session bean的annotation的繼承是有條件的, 就是class level比方說@Stateless, @Stateful會被忽略, 不過lifecycle callback會被繼承下來.
  • session bean的business method name不能以ejb開頭, 比方說不能是ejbDoit()
  • session bean的method必須是public且不能是static或final
  • 使用一個remote business interface要注意argument與return type必須實作Serizable
  • 所有session 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实例化session bean後调用@PostContruct, container移除session 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的定義
    1. 屬性有name, mappedName, description
    2. name屬性用來指定bean的name, 有的container用來和JNDI綁定. 如果name沒有設定就會是bean的class name.
    3. mappedName是vender-specific(特定于厂商), 也就是依不同container有不同的情形. 以GlassFish來說是將mappedName的值綁定到JNDI name.
  • @Local: stateless session bean的local interface, local interface表示這個session bean和client放在同一個JVM上執行.
  • @Remote: 當client存在於container外的JVM時就必須使用@Remote
    1. 一個@Remote interface可以繼承java.rmi.Remote
       public interface TestRemote extends Remote { ... } 
      就算程序裡面沒寫繼承Remote, container還是會在byte code階段插入繼承Remote的動作
    2. 沒有程序上繼承java.rmi.Remote的好處就是不用處理java.rmi.RemoteException
    3. @Remote business interface有個需求就是所有的參數與回傳值都必須是Serializable, 因為這樣才能通過RMI
  • @WebService: 透過@WebService可讓session bean成為SOAP-based web service. 唯一要做的就是在interface上加上@WebService.
  • 不能讓一個business interface同時@Local又@Remote或是又@WebService, 不過可以透過interface的繼承改變要使用的是@Remote session bean還是@Local的 session bean.
  • 放session bean的lifecycle callback
  • 可以有多個@PostConstruct, @PreDestroy (不過我試起來一個session bean就只能一個lifecycle callback有效, 頂多除了callback以外還指定interceptor, 就加上interceptor的一個lifecycle callback有效.)
  • lifecycle callback要符合pattern: void < METHOD >()
  • interceptor內的lifecycle callback要符合pattern: Object < METHOD >(InvocationContext) throws Exception, 然後記得回傳InvocationContext.proceed, 除非打算不繼續執行. (可參考EJB3 Interceptor)
  • session bean的lifecycle callback不可有checked exception, interceptor的則可以.
  • session 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直到client離開或stateful session bean destroy為止. 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, 就是因為無法serialize該object的關係. 如果要使用不須serialize的class 成员只要用transient声明該class member或在@PrePassivate把class member改成null再於@PostActivate設定回來即可.
  • 使用stateful session bean的方式幾乎和stateless session bean的方式幾乎一樣, 唯一不一樣的是stateful session bean的business interface只能使用@Local與@Remote而不能用@WebService. 因為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, @PostActivate也可放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用來注入session bean到client code. @EJB有幾個屬性: name, beanInterface, beanName. name用來指定JNDI name, beanName則是當一個interface有兩個實作時用來決定要注入哪個實作.
  • 使用@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造成效能變差太多.
  • 分享到:
    评论

    相关推荐

      EJB2 SessionBean

      **EJB2 SessionBean**是Java企业版...尽管现代Java EE(现称为Jakarta EE)已经发展到了EJB3.x和更高级别,但理解EJB2 SessionBean的基本概念和工作原理对理解整个企业级应用开发的历史和演进仍然是非常有价值的。

      EJB3图文教程之开发Session Bean

      ### EJB3图文教程之开发Session Bean:详细解析与实践指南 #### 一、环境搭建:JBuilder2007与JBoss4.0的完美结合 在开始EJB3.0的Session Bean开发之前,首先需搭建一个适宜的开发环境。本教程将指导你如何在...

      EJB详解 sessionbean entitybean MDB

      它可以是无状态的(Stateless Session Bean),为每个请求创建新的实例,或者有状态的(Stateful Session Bean),维护与特定客户端会话的状态。 - **Entity Bean**:用于表示数据库中的持久化对象,实现业务实体的...

      EJB3.0无状态SessionBean例子

      3. **本地接口的SessionBean** 本地接口通常用于同一应用内部的组件间通信。在示例中,`EJB-HelloWorld`可能包含了名为`HelloWorldLocal`的本地接口,其中定义了业务方法,如`sayHello()`。然后,在Bean类中,通过`...

      EJB_sessionbean.rar_session

      **EJB Session Bean详解** Enterprise JavaBeans (EJB) 是Java平台企业版(Java EE)的核心组成部分,它为构建可扩展、安全且事务处理的分布式应用程序提供了强大的框架。EJB中的Session Bean是其中一类重要的组件...

      ejb sessionbean demo

      在"ejb sessionbean demo"中,我们主要探讨的是如何使用EJB的Session Bean进行开发和演示。Session Bean通常用于实现业务逻辑,它们可以是无状态的,意味着每个请求都会创建一个新的Bean实例,不保留任何先前会话的...

      EJB3.0开发Session Bean.rar

      **企业级JavaBeans (EJB) 3.0:核心概念与Session Bean详解** 企业级JavaBeans(Enterprise JavaBeans,简称EJB)是Java平台上用于构建可部署在服务器端的企业级应用的重要组件模型。EJB 3.0是EJB规范的一个重大...

      ejb实例包括session bean和实体bean

      3. **Entity Beans 3.0(EJB 3.0引入)**:简化了Entity Bean的使用,采用了注解(Annotations)方式,使得持久化过程更为简洁,与JPA(Java Persistence API)紧密集成。 **EJB的生命周期** 无论是Session Bean...

      ejb入门录像 sessionBean

      【ejb入门录像 sessionBean】是针对企业级Java应用(Enterprise JavaBeans,简称EJB)技术的初学者设计的一段教学视频。EJB是Java EE(Java Platform, Enterprise Edition)框架的重要组成部分,它提供了一种标准的...

      EJB的开发及应用,Session Bean的开发

      3. **部署描述符** - 编写ejb-jar.xml文件,其中包含关于EJB的元数据,如Bean的类型、JNDI名称等。 4. **容器配置** - 在应用服务器中配置EJB容器,指定EJB的部署位置和资源。 5. **客户端调用** - 客户端通过JNDI...

      EJB3.0开发Session Bean

      通过上述步骤,我们不仅学习了如何在JBuilder2007中配置和使用JBoss4.0,还掌握了EJB3.0 SessionBean的开发流程,从项目创建、SessionBean设计、方法实现到最终的部署和测试。这为开发复杂的企业级应用提供了一个...

      ejb3实例(包括sessionbean和entitybean)

      1. SessionBean类:包含@Stateless或@Stateful注解的Java类,表示业务逻辑。 2. EntityBean类:带有@Entity注解的Java类,对应数据库表的实体。 3. 数据源配置文件:如context.xml或application.xml,定义JNDI数据源...

      ejb3整合Struts1.x实例

      3. **EJB3 Session Bean**:创建EJB3 Session Bean来封装业务逻辑。Session Bean可以调用JPA API来操作数据库,如`EntityManager`和`EntityManagerFactory`。使用`@Stateless`或`@Stateful`注解标记Bean的类型。 4....

      EJB容器对bean的管理

      对于无状态session bean(Stateless session bean),EJB容器会在启动时预先创建一定数量的bean实例放入实例池。当客户端请求服务时,容器会从池中取出一个实例,处理完请求后,再将实例放回池中。这样,池中的每个...

      学习SessionBean

      SessionBean是Java EE(Enterprise Edition)中企业级JavaBeans(EJB)的一部分,主要用于实现服务器端的业务逻辑。它是一个可复用的组件,可以处理客户端的会话状态,提供了在分布式环境中持久化用户会话的能力。本...

      Session Bean的使用

      JavaBean和Session Bean是Java企业级应用开发中的重要概念,特别是在使用Enterprise JavaBeans(EJB)技术时。本文将深入探讨这两个概念,以及如何在实际项目中使用它们。 首先,让我们了解什么是JavaBean。...

      EJB消息驱动bean Demo

      在EJB中,消息驱动bean(Message-Driven Bean,MDB)是一种特殊类型的bean,它用于处理来自消息中间件(如JMS,Java Message Service)的消息。在这个“EJB消息驱动bean Demo”中,我们将深入探讨EJB MDB和JMS如何...

    Global site tag (gtag.js) - Google Analytics