4 Replies Latest reply on Oct 8, 2009 11:46 AM by daziplqa

    Stateful session beans don't keep state !!!

      Hi folks,

      I am new to EJB and statefull sessin beans on JBoss4.2 AS
      I have the following urgent problem:


      I have the following statefull session bean.

      @Stateful
      public class PlaceOrderBean implements PlaceOrder {
       private ShippingInfo shippingInfo;
       private BillingInfo billingInfo;
      
       public void setShippingInfo(ShippingInfo shippingInfo) {
       System.out.println("Call # : 1 " );
       this.shippingInfo = shippingInfo;
       }
      
       public void setBillingInfo(BillingInfo billingInfo) {
       System.out.println("Call # : 2 " );
       this.billingInfo = billingInfo;
       System.out.println(shippingInfo.getShippingInfo()); // << NullPointerException here !!!!! how come ??!!
       }
      }
      

      The client :
      // this class is a JSF managed bean that is used with 2 JSPs, each one of the two calles on of the below methods
      public class OrderItemBean {
       private PlaceOrder placeOrder;
      
       public OrderItemBean() {
       try {
       logger.info("Getting PlaceOrder instance ...");
       InitialContext ctx = new InitialContext();
       placeOrder = (PlaceOrder) ctx.lookup("chapter2/" + PlaceOrderBean.class.getSimpleName() + "/local");
       }catch(NamingException ex) {
       ex.printStackTrace();
       }
       }
       // Note, the class OrderItemBean get instantiated a new instance before calling the following method
       // so, the JNDI code in the constructor above is being called to lookup the statefull bean
       public String setShippingInfo() {
       ShippingInfo shipInfo = new ShippingInfo();
       shipInfo.setShippingInfo(getShippingInfoTxt().getValue().toString());
       placeOrder.setShippingInfo(shipInfo);
      
       System.out.println("shipping Info : " + shipInfo.getShippingInfo());
      
       return SUCCESS + "_setShippingInfo";
       }
       // Note, the class OrderItemBean get instantiated a new instance before calling the following method
       // so, the JNDI code in the constructor above is being called again to lookup the statefull bean
       public String setBillingInfo() {
       BillingInfo billingInfo = new BillingInfo();
       billingInfo.setBillingInfo(getBillingInfoTxt().getValue().toString());
       placeOrder.setBillingInfo(billingInfo);
      
       setAdditionalInfo();
      
       return SUCCESS + "_setBillingInfo";
       }
      
      }


      The code above get this exception

      03:06:35,264 INFO [OrderItemBean] Getting PlaceOrder instance ...
      03:06:35,274 INFO [STDOUT] Call # : 1
      03:06:35,274 INFO [STDOUT] shipping Info : Cairo, Egypt, Elobour city
      03:06:36,919 INFO [OrderItemBean] Getting PlaceOrder instance ...
      03:06:36,929 INFO [STDOUT] Call # : 2
      03:06:36,930 FATAL [application] javax.ejb.EJBException: java.lang.NullPointerException
      javax.faces.el.EvaluationException: javax.ejb.EJBException: java.lang.NullPointerException
       at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:91)
       at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:91)
       at javax.faces.component.UICommand.broadcast(UICommand.java:383)
       at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:447)
       at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:752)
       at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:97)
       at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
       at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
       at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241)
       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
       at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:580)
       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
       at java.lang.Thread.run(Thread.java:619)
      
      .............
      ..............
      


      How this come, Ain't it as stateFULL session bean !!!!!!

      Please Help

        • 1. Re: Stateful session beans don't keep state !!!
          wolfgangknauf

          Hi,

          according to your code comments, you call "setShippingInfo", then a new instance of your OrderItemBean is created, and after this "setBillingInfo" is called.
          This cannot work with a Stateful bean, because you will get a new, clean instance on each lookup. The state will only be kept if you save it in some member variable.

          To work around this you might place the EJB in the session (or in the request):

          HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false;
          session.setAttribute("myPlaceOrder", placeOrder);


          Later, you can reuse the "placeOrder" instance by reading it from the HttpSession.

          Hope this helps

          Wolfgang

          • 2. Re: Stateful session beans don't keep state !!!

            Thank, I get it.

            So, You mean to be able to use the statefullness of statefull session beans, I should keep a single instance of the bean.

            But, If i use a state**less** bean, and i kept a single instance from it while setting the bean data, It should save the same date.

            In other words, If I have changed the constructor above to a static initialize block, then change the stateFul bean to a stateLess bean, I will get code will still works, I just tried it.
            So, What is the story behind that?

            • 3. Re: Stateful session beans don't keep state !!!
              peterj

              When the client asks for an EJB, it gets a proxy for the EJB, not the EJB itself.

              If the proxy is for a stateless bean (SLSB), when the client calls a method on the proxy, the server allocates a bean from a pool. Once the method is completed the bean is placed back in the pool. Any subsequent calls to methods on the SLSB repeat this pattern.

              If the proxy is for a stateful bean (SFSB) then the server allocate a bean specifically for that proxy. As long as the client calls methods on that proxy the same SFSB will handle the calls. If the client does another lookup, it gets a new proxy and a new SFSB instance for that proxy.

              Hope that explanation helps.

              • 4. Re: Stateful session beans don't keep state !!!

                Thanks perter very much, It was very explanatory