3 Replies Latest reply on Mar 28, 2006 3:04 AM by Sacha Labourey

    My first SFSB barfed...

    tsar_bomba Newbie

      So, I'm a grand spankin' greenhorn newbie...and I'm attempting to create a Stateful session bean using JBoss 4.0.4RC1 (on Windows).

      I've got a small storefront application that has several Entity beans and SLSBs that have so far worked great...I'm not having any problems w/ my entities or stateless beans...very impressed so far.

      However, I just created a ShoppingCart SFSB that throws an exception telling me it can't be found...even though it appears to be discovered by the server when deployed...so I'm obviously doing *somthing* wrong.

      Most of my work has been by reference to the TrailBlazer sample app, which has been a great learning tool so far.

      Here's the exception I'm getting:

      10:19:05,275 ERROR [STDERR] javax.ejb.EJBNoSuchObjectException: Could not find Stateful bean: 4snf2b-wb57nw-elb23ltf-1-elb2fol7-9
      10:19:05,275 ERROR [STDERR] at org.jboss.ejb3.cache.simple.SimpleStatefulCache.get(SimpleStatefulCache.java:251)
      10:19:05,275 ERROR [STDERR] at org.jboss.ejb3.stateful.StatefulInstanceInterceptor.invoke(StatefulInstanceInterceptor.java:59)
      10:19:05,275 ERROR [STDERR] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
      10:19:05,275 ERROR [STDERR] at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:78)
      10:19:08,620 ERROR [STDERR] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
      10:19:08,620 ERROR [STDERR] at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47)
      10:19:08,620 ERROR [STDERR] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
      10:19:08,620 ERROR [STDERR] at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
      10:19:08,620 ERROR [STDERR] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
      10:19:08,620 ERROR [STDERR] at org.jboss.ejb3.stateful.StatefulContainer.localInvoke(StatefulContainer.java:190)
      10:19:08,620 ERROR [STDERR] at org.jboss.ejb3.stateful.StatefulLocalProxy.invoke(StatefulLocalProxy.java:98)
      10:19:08,620 ERROR [STDERR] at $Proxy102.addOrderLine(Unknown Source)
      10:19:08,620 ERROR [STDERR] at com.myapp.proxy.CartProxy.addOrderLines(CartProxy.java:51)
      


      Here's the method in CartProxy.java that's throwing the exception:

       public static void addOrderLines(Map<Configuration, Integer> orderLines)
       {
       ShoppingCart cart = null;
      
       try
       {
       //get EJB
       InitialContext ctx = new InitialContext();
       cart = (ShoppingCart)ctx.lookup(localEJB);
      
       //get collection from map
       int size = orderLines.size();
       Iterator i = orderLines.entrySet().iterator();
      
       //iterate over map
       for (int x=0; x<=size; x++)
       {
       //get key/value pair
       Entry entry = (Entry)i.next();
       Configuration cfg = (Configuration)entry.getKey();
       Integer qty = (Integer)entry.getValue();
      
       //build OrderLine
       OrderLine ol = new OrderLine();
       ol.setConfiguration(cfg);
       ol.setQuantity(qty);
      
       //add to cart SFSB
       cart.addOrderLine(ol);
      
       //TEMPORARY!!
       cart.checkout(); //cancel session
       }
       }
       catch (NamingException exp)
       {
       // TODO Auto-generated catch block
       exp.printStackTrace();
       }
       catch (Exception exp)
       {
       // TODO Auto-generated catch block
       exp.printStackTrace();
       }
       }
      }
      


      ...it takes a Map, collected in the UI, creates an OrderLine entity bean, and adds each entity to the ShoppingCart.

      Here's the SFSB (and interfaces):

      public interface ShoppingCart
      {
       void addOrderLine(OrderLine item);
       @Remove void checkout();
      }
      
      @Stateful
      public class ShoppingCartBean
       implements ShoppingCartLocal, ShoppingCartRemote, Serializable
      {
       private List<OrderLine> orderLines;
       @EJB private ProductsLocal products;
      
       public ShoppingCartBean()
       {
       orderLines = new ArrayList<OrderLine>();
       }
      
       public void addOrderLine(OrderLine item)
       {
       this.orderLines.add(item);
       }
      
       @Remove
       public void checkout()
       {
       System.out.println("To be implemented");
       }
      }
      
      @Local
      public interface ShoppingCartLocal extends ShoppingCart
      {
      }
      
      @Remote
      public interface ShoppingCartRemote extends ShoppingCart
      {
      }
      


      Now...it's saying it can't be found...which is odd because I see this when I deploy the app:

      10:18:39,885 INFO [Ejb3AnnotationHandler] found EJB3: ejbName=ShoppingCartBean, class=com.myapp.session.ShoppingCartBean, type=STATEFUL
      


      And, you'll notice the @Remove method in my SFSB, it is actually writing the output in the method *before* the exception is thrown!! I can see this when running the app and calling the @Remove method:

      10:19:05,275 INFO [STDOUT] To be implemented
      


      Any ideas? Thanks very much!

        • 1. Re: My first SFSB barfed...
          Andrew May Newbie

          The problem is that you are creating a SFSB when you perform the JNDI lookup, and then your call to checkout() is causing it to be removed because of the @Remove annotation. After that point you can no longer use that cart instance, so it fails the second time around your for loop.

          The error you are getting is not that the JNDI lookup is failing - it is failing to find that particular instance of the bean because it has been removed from the bean cache (hence the "4snf2b-wb57nw-elb23ltf-1-elb2fol7-9", which is an internal identifier for that bean instance).

          This has all changed from EJB 2.x, but I imagine that you can obtain a new cart by calling ctx.lookup() again.

          Alternatively, you could remove the @Remove annotation from the checkout method. As long as you are careful to re-set any state in your implementation of checkout you can continue to use the same instance of the bean.

          It's good to still have a method that removes the bean when you are finished with it - but it could just be a no-op method that you call after the loop in your proxy.

          Hope that helps,
          Andrew

          • 2. Re: My first SFSB barfed...
            tsar_bomba Newbie

            Yes, thank you, I'm a real dork for missing that! I *meant* to have checkout() one line down from where it was...I didn't meant to @Remove it from the session *during* the loop.

            Thanks for catching that!

            • 3. Re: My first SFSB barfed...
              Sacha Labourey Master

              Bill,

              Shouldn't replace this horrible stacktrace by a debug level message? It is certainly an exception for the client side but such a thing is quite fine for the server side (session could have timed-out, etc.)

              Cheers,

              sacha