5 Replies Latest reply on Feb 23, 2011 3:02 PM by kibojan

    Conversation Scope in Weld 1.1.0-Beta2 (with Glassfish 3.1)

    swiegersf.francois.swiegers.gmail.com

      Good day,


      I am using SFSB together with the ConversationScope in order to have reentrant access to the same SFSB instance from a Hessian client, like so:



      @Stateful
      @ConversationScoped
      public class MySfsb {
      
        @Inject Conversation conversation;
      
        public void start() {
          conversation.begin();
        }
      
        ...
      
      }



      I then use the CID conversation parameter to propagate my request from my remote Hession client, using a request paramater.


      This all works in Jboss 6 M5 and Glassfish 3.1 build 28. However, from build 31 onwards, Glassfish is using Weld 1.1.0-Beta2, and now the Conversation context in Glassfish is not active anymore for the above scenario:


      org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.ConversationScoped
           at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:639)
           at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:73)
           at org.jboss.weld.bean.proxy.AbstractBeanInstance.invoke(AbstractBeanInstance.java:48)
      



      What is the right way to use the conversation scope in a JavaEE 6 application that does not use JSF, but has a servlet entry point? I looked at Seam-Remoting, but the trunk version still uses Weld 1.0.1's ConversationManager, which I can't find in Weld 1.1.0-Beta2. I also looked at the ConversationContext from Weld SPI, like so:


      public class MyHessionEntryPoint extends HessianServlet {
      
      @Inject
      @Http
      private ConversationContext conversationContext;
      
        @Override
        public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException {
      
        String id = request.getParameter("cid");
        if (id != null) {
          conversationContext.activate(id);
        } else {
          conversationContext.activate();
        }
        super.service(request, response);
        }
      
      }
      



      With this code, the ConversationScope is active again, but my long running conversations do not get restored upon activate(cid), resulting in NullPointerExceptions in my SFSB.


      Is there some documentation that explains how to activate and manage conversations?

        • 1. Re: Conversation Scope in Weld 1.1.0-Beta2 (with Glassfish 3.1)
          swiegersf.francois.swiegers.gmail.com

          OK, to simplify a bit, I took a look at the ExecutorHandler from Seam Remoting (the real latest one from 
          github), and according to how they do things, the following should work:


          public class MyServlet extends HttpServlet {
          
               private static final long serialVersionUID = 1L;
          
               @Inject
               @Http
               ConversationContext conversationContext;
          
               @Inject
               Conversation conversation;
          
               @Inject
               BeanManager beanManager;
          
               @Override
               protected void service(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
          
                    String cid = request.getParameter("cid");
          
                    conversationContext.activate(cid);
                    try {
                         Bean<?> bean = beanManager.getBeans(MyConversation.class)
                                   .iterator().next();
                         CreationalContext<?> ctx = beanManager
                                   .createCreationalContext(bean);
                         MyConversation mc = (MyConversation) beanManager.getReference(bean,
                                   MyConversation.class, ctx);
          
                         String out = mc.increment();
                         response.getOutputStream().println("<html><p>");
                         response.getOutputStream().println(
                                   "Value for " + conversation.getId() + " is : " + out);
                         response.getOutputStream().println("</p></html>");
                         response.getOutputStream().close();
                    } finally {
                         conversationContext.deactivate();
                    }
               }
          
               @ConversationScoped
               public static class MyConversation implements Serializable {
          
                    private static final long serialVersionUID = 1L;
          
                    @Inject
                    Conversation conversation;
          
                    private int num;
          
                    public String increment() {
                         if (conversation.isTransient()) {
                              conversation.begin();
                         }
                         return String.valueOf(num++);
                    }
          
               }
          
          }
          



          The above servlet should allow the user to increment the value in a conversation by simply appending the cid parameter to the servlet URL.


          However, it simply does not work. The


          conversationContext.activate(cid)



          method simply creates a new conversation, regardless of whether that conversation ID was generated and made non-transient in a previous request.


          Does Weld support conversations from servlets? I don't mind doing a little non-portable tap-dancing, but if Weld does not currently support this, can you please let me know?


          thanks

          • 2. Re: Conversation Scope in Weld 1.1.0-Beta2 (with Glassfish 3.1)
            swiegersf.francois.swiegers.gmail.com

            Just an update to this, I made the above code work by simply adding


            request.getSession();
            



            as the first statement in my servlet. It seems that the ConversationManager requires the session to be instantiated before calling the deactivate() method, which is reasonable. It is only in small example apps that the session would not be created by the time the conversation is deactivated. :)


            • 3. Re: Conversation Scope in Weld 1.1.0-Beta2 (with Glassfish 3.1)
              cjalmeida

              Yet, this is a hard to debug problem. Should be part of the Javadoc.

              • 4. Re: Conversation Scope in Weld 1.1.0-Beta2 (with Glassfish 3.1)
                ssamayoagt
                FWIW, Same with Tomcat 7 + weld 1.1.0CR1, I mean:

                request.getSession();

                Regards.
                • 5. Re: Conversation Scope in Weld 1.1.0-Beta2 (with Glassfish 3.1)
                  kibojan

                  Thanks for the tip. Really helpful.
                  I like when people share their findings. :)