当前位置: 首页 > 知识库问答 >
问题:

为什么无状态和有状态会话bean的行为不如预期

顾乐池
2023-03-14
public class Test1(){  
  public vod method1(){  
    try{  
        Hashtable<String, String> env = new Hashtable<String, String>();  
        env.put(Context.INITIAL_CONTEXT_FACTORY, EJB_JNDI_FACTORY);  
        env.put(Context.PROVIDER_URL, EJB_URL);  
        InitialContext ctx = new InitialContext(env);             
        LogSearchRemote logSearchRemote = (LogSearchRemote) ctx.lookup(LOG_SEARCH_EJB_BINDNAME);  
        System.out.println("logSearchRemote = " + logSearchRemote);  
        logSearchRemote.setTest(5);  
        System.out.println("logSearchRemote.getTest() = " + logSearchRemote.getTest());  
        System.out.println("logSearchRemote.getTestAgain() = " + logSearchRemote.getTestAgain());  
        LogSearchRemote logSearchRemote2 = (LogSearchRemote) ctx.lookup(LOG_SEARCH_EJB_BINDNAME);  
        System.out.println("logSearchRemote2 = " + logSearchRemote2);  
        System.out.println("logSearchRemote2.getTest() = " + logSearchRemote2.getTest());  
        System.out.println("logSearchRemote2.getTestAgain() = " + logSearchRemote2.getTestAgain());  
        this.session = session;  
        session.setAttribute("LogSearchEJB", logSearchRemote);  
        System.out.println("logSearchRemote = " + logSearchRemote);  
    }catch(Exception e){  
        e.printStackTrace();  
    }  
  // if @stateless, throw exception "$Proxy53 cannot be cast to hk.gov.ehr.service.tch.als.admin.logsearch.ejb.LogSearchRemote"  
  // if @stateful, no error!!  
LogSearchRemote logSearchRemote = (LogSearchRemote)session.getAttribute("LogSearchEJB");  
  //.....  
  }  
}   

1)对于上面的代码,如果LogSearchRemote实现bean是有状态的,那么

   LogSearchRemote logSearchRemote = (LogSearchRemote)session.getAttribute("LogSearchEJB");

没有错误,但是如果LogSearchRemote实现bean是无状态的,那么会抛出异常“$Proxy53不能强制转换为hk.gov.ehr.service.tch.als.admin.logsearch.ejb.LogSearchRemote”,为什么?

2)对于有状态会话bean,每次

LogSearchRemote logSearchRemote = (LogSearchRemote) ctx.lookup(LOG_SEARCH_EJB_BINDNAME); 

返回不同的logSearchRemote实现bean,
但如果是无状态会话bean,则每次

LogSearchRemote logSearchRemote = (LogSearchRemote) ctx.lookup(LOG_SEARCH_EJB_BINDNAME);   

返回相同的bean!!
为什么会这样?
我认为无状态会话bean不应该保持状态,并且每次查找都应该返回不同的实现bean。

@Stateless(name = "AlsAdminLogSearch_1_0", mappedName = "ejb/AlsAdminLogSearch_1_0")  
public class LogSearchBean implements LogSearchRemote{  

    private int test;

    @Override  
    public void setTest(int value){  
        test = value;  
    }  

    @Override  
    public int getTest(){  
        return test;  
    }  

    @Override  
    public int getTestAgain(){  
        return test;  
    }  

//...methods  

}    
logSearchRemote.setTest(5);  
System.out.println("logSearchRemote.getTest() = " + logSearchRemote.getTest());  
System.out.println("logSearchRemote.getTestAgain() = " 
logSearchRemote.getTestAgain());   

为什么它会记得?无状态会话bean不应该为每个方法调用调用不同的EJB实例

共有1个答案

彭霄
2023-03-14

无状态会话bean应该“以无状态的方式”使用,但实际上服务器保留了一个实例池(依赖于供应商策略)。因此,在几次查找中,您可能会收到完全相同的实例,但这是无法保证的。相反,不同的线程和客户机实例可以获得相同的无状态EJB实例,从而有效地共享该无状态EJB实例。这就是为什么无状态EJB不应该在内部持有任何“业务逻辑状态”,因为您不知道下一个客户机是哪个。虽然不推荐使用,但无状态EJB当然可以保持某种内部技术状态,这可能使它能够在实例重用时更快地访问外部“无状态”资源。(请参见web和书籍中的EJB生命周期图。)

另一方面,有状态会话bean应该“以有状态的方式”使用,也就是说,它们打算在一段时间内保存状态,并跨越多个客户机请求。因此,保证客户机在查找时接收到“新实例”,并且由于容器不能确定在上一个使用周期结束后是否有任何实现“忘记”旧的状态信息,因此容器在将有状态EJB与客户机分离后简单地销毁它们,并在查找时创建一个新实例。

这样做的问题是,有状态EJB的客户机必须在整个计划的使用周期内持有并保持其对EJB的引用,因为在丢失(最后)引用后,有状态EJB在空间中丢失,并由容器清理。另一方面,EJB引用是不可序列化的(据我所知),因此客户机在其EJB使用周期中不需要序列化,以保持其EJB引用的存活。

因此,在一个项目中,有状态EJB被用来保存一些用户会话信息,比如说几个小时,我们决定使用HttpSession属性对象来保存有状态EJB引用。因此,应用程序可以在HttpSession中查找“EJB Holder”对象,然后重用有状态EJB。但是,如果web容器决定序列化HttpSession属性对象(“EJB holder”),这显然是失败的,因为EJB引用不能在序列化后存活。下次在HttpSession范围内查找“EJB Holder”时,它会被web容器反序列化,但是有状态EJB会被切断它的引用,不能再使用了。

 类似资料:
  • 我是JavaEE的新手,我试图找出无状态和有状态会话bean之间的区别。到目前为止我所理解的: 1.)在有状态会话bean中,bean的状态与客户机绑定;因此,只要我们与同一个用户在同一个会话中,就应该有相同的bean实例状态 2.)在无状态会话bean中,没有绑定到会话和客户机的状态;事实上,bean实例可以在用户的每次调用或请求中进行交换 为了尝试这一点,我编写了一个简短的servlet,它只

  • 有状态会话bean定义如下: 无状态会话bean无状态会话bean不维护与客户端的会话状态。当客户机调用无状态bean的方法时,该bean的实例变量可能包含特定于该客户机的状态,但仅限于调用期间。当方法完成时,客户端特定状态不应保留。然而,客户端可能会更改池化无状态bean中实例变量的状态,并且此状态将保留到下一次调用池化无状态bean时。除了在方法调用期间,无状态bean的所有实例都是等效的,允

  • 问题内容: Java中的无状态Bean不会在两次客户端调用之间保持其状态。因此,简而言之,我们可以将它们视为具有业务方法的对象。每个方法都带有参数并返回结果。调用该方法时,将在执行堆栈中创建一些局部变量。当该方法返回时,将本地对象从堆栈中删除,并且如果分配了一些临时对象,则无论如何都会对其进行垃圾回收。 在我看来,这与通过单独的线程调用同一实例的方法没有什么不同。那么,为什么容器不能使用bean的

  • 问题内容: 我正在学习EJB3,只是好奇何时可以方便地使用SFSB?当SFSB确实可以轻松解决一些复杂问题时,我找不到任何很好的示例。 实际上,我看到SLSB可以用作Web服务,这很方便。但我不知道何时使用SFSB。我只看到它的问题,因为我们应该学习一些有关它的知识,我们应该编写由批注组成的代码,其内容要少于完全注释,我们应该使用烦人的查找方法……而我们得到的任何回报都没有。 例如,我们不能使用S

  • 我对口水还不熟悉。我试图理解Drools提供的无状态会话和有状态会话之间的区别。 根据我的初步理解, 在无状态会话的情况下,如果在任何规则的操作执行过程中修改了事实,则不会将其重新提交给推理引擎以找出与修改后的事实匹配的新规则。 在状态会话的情况下,如果在任何规则的操作执行过程中修改了事实,则它将被重新提交给推理引擎以找出与修改后的事实相匹配的新规则,然后执行相应的操作。 因此,当我试图通过编写一

  • 问题内容: 有状态会话bean和HTTP会话之间有什么关系吗?我们将需要有状态会话Bean的用例是什么,而HTTP会话需要哪些用例。我可以将有状态会话Bean公开为静态Web服务吗? 问题答案: HTTP是一种无状态协议, 这意味着 它是服务器和客户端之间的实际传输协议- 是“无状态的, 因为它在调用之间不记得任何东西。 现在,首先阅读一下什么是HTTPSession和什么是Session Bea