2 Replies Latest reply on Jun 13, 2007 7:48 PM by Pete Muir

    Conversations - do not work in Seam 1.2.1?

    Bradley Smith Master

      I'm working on some code where I am trying to do the following:

      1. User clicks a link to an action method on a SFSB
      2. method is annotated with @Begin, using a custom conversation id
      2a. the custom conversation id comes from the following
      2a-1. a @Factory method in a SLSB creates a new persistent entity; the id of this entity will be appended to a String to create a custom conversation id
      2a-2. the @Factory class would like to use the existing persistent entity if possible (avoid creating new persistent or querying for existing persistent entity) - thus, I have an @In for the entity.
      2a-3. here is the class with the @Factory method:

      @Stateless
      @Name("draftAccessRequestFinder")
      public class DraftAccessRequestFinderBean implements DraftAccessRequestFinder {
      
       @Logger
       private Log log;
      
       @PersistenceContext(unitName = "accessControlDatabase")
       private EntityManager em;
      
       @In
       private Principal userPrincipal;
      
       @In("#{conversation.id}")
       private String conversationId;
      
       @In(required = false) @Out(scope= ScopeType.CONVERSATION)
       private DraftAccessRequestMaster draftAccessRequestMaster;
      
       @Factory("draftAccessRequestMaster")
       public DraftAccessRequestMaster createMaster() {
       log.info("DraftAccessRequestFinderBean.createMaster() : conversationId -> "+conversationId);
       log.info("DraftAccessRequestFinderBean.createMaster() : draftAccessRequestMaster -> "+draftAccessRequestMaster);
       // create or load draftAccessRequest....
       if (conversationId != null && conversationId.indexOf(':')>0 && draftAccessRequestMaster == null) {
       long id = Long.valueOf(conversationId.substring(conversationId.indexOf(':')+1));
       draftAccessRequestMaster = em.find(
       DraftAccessRequestMaster.class, id
       );
       log.info("loaded draftAccessRequestMaster -> "+draftAccessRequestMaster);
       }
      
       if (draftAccessRequestMaster == null) {
       if (userPrincipal == null) {
       throw new RuntimeException("userPrincipal is null.");
       }
       if (!(userPrincipal instanceof UserPrincipal)) {
       throw new RuntimeException("userPrincipal is not an instance of com.evergreen.jaas.UserPrincipal.");
       }
       draftAccessRequestMaster = new DraftAccessRequestMaster();
       draftAccessRequestMaster.setUserId(
       ((UserPrincipal) userPrincipal).getUserid()
       );
       draftAccessRequestMaster.setUserName(
       ((UserPrincipal) userPrincipal).getPersonName()
       );
       em.persist(draftAccessRequestMaster);
       em.flush(); // we need to obtain a PK for this entity now...
       }
       return draftAccessRequestMaster;
       }
      }
      


      3. here is the SFSB that wants the custom conversation id as well as a reference to the persistent entity:

      @Stateful
      // Seam - defaults to Conversational context...
      @Name("accessRequestManager2")
      public class AccessRequestManager2Bean implements AccessRequestManager2 {
      
       @Logger
       private Log log;
      
       @PersistenceContext(unitName = "accessControlDatabase")
       private EntityManager em;
      
       @In
       private UserPrincipal userPrincipal;
      
       // for development purposes only - todo remove this
       @In
       private Conversation conversation;
      
       @In(create=true) @Out(scope= ScopeType.CONVERSATION)
       private DraftAccessRequestMaster draftAccessRequestMaster;
      
       @Out
       private List<String> errors = new ArrayList<String>();
      
      
       /**
       * Start a new add-access request. This method also generates the conversationId to
       * use in the conversation that beans of this class are associated with.
       *
       * This is complicated - in 1 swoop, we need to
       * 1 - create the DraftAccessRequestMaster for the conversation component
       * 2 -
       */
       @Begin(id = "DraftAccessRequestID:#{draftAccessRequestMaster.id}", join = true)
       public void startAddRequest() {
       log.info("startAddRequest()");
       log.info(conversation);
       log.info("conversation.id = " + conversation.getId());
       log.info("conversation.parentId = " + conversation.getParentId());
      
       if (draftAccessRequestMaster == null) {
       log.info("draftAccessRequestMaster is null...not expected.");
       }
       ....
       }
      }
      


      4. here is a link that calls the SFSB method:

       <s:link action="#{accessRequestManager2.startAddRequest}" value="Add 2"
       title="Add entitlements to an application for a user.">
       </s:link>
      


      5. and here is a log of what occurs

       First click of link...
      
      10:53:32,805 INFO com.evergreen.accesscontrol.impl.DraftAccessRequestFinderBean - DraftAccessRequestFinderBean.createMaster() : conversationId -> 3
      10:53:32,805 INFO com.evergreen.accesscontrol.impl.DraftAccessRequestFinderBean - DraftAccessRequestFinderBean.createMaster() : draftAccessRequestMaster -> null
      10:53:32,805 INFO com.evergreen.accesscontrol.entity.DraftAccessRequestMaster - new DraftAccessRequestMaster()
      10:53:32,821 INFO com.evergreen.accesscontrol.impl.AccessRequestManager2Bean - startAddRequest()
      10:53:32,821 INFO com.evergreen.accesscontrol.impl.AccessRequestManager2Bean - org.jboss.seam.core.Conversation@54d3dd
      10:53:32,821 INFO com.evergreen.accesscontrol.impl.AccessRequestManager2Bean - conversation.id = DraftAccessRequestID:50
      10:53:32,821 INFO com.evergreen.accesscontrol.impl.AccessRequestManager2Bean - conversation.parentId = null
      
       Second click of link (expecting to find draftAccessRequestMaster in memory for conversation but it's not found...)
      
      10:53:36,915 INFO com.evergreen.accesscontrol.impl.DraftAccessRequestFinderBean - DraftAccessRequestFinderBean.createMaster() : conversationId -> DraftAccessRequestID:50
      10:53:36,915 INFO com.evergreen.accesscontrol.impl.DraftAccessRequestFinderBean - DraftAccessRequestFinderBean.createMaster() : draftAccessRequestMaster -> null
      10:53:36,930 INFO com.evergreen.accesscontrol.entity.DraftAccessRequestMaster - new DraftAccessRequestMaster()
      10:53:36,930 INFO com.evergreen.accesscontrol.impl.DraftAccessRequestFinderBean - loaded draftAccessRequestMaster -> DraftAccessRequestMaster{...}
      10:53:36,930 INFO com.evergreen.accesscontrol.impl.AccessRequestManager2Bean - startAddRequest()
      10:53:36,930 INFO com.evergreen.accesscontrol.impl.AccessRequestManager2Bean - org.jboss.seam.core.Conversation@adf2c7
      10:53:36,946 INFO com.evergreen.accesscontrol.impl.AccessRequestManager2Bean - conversation.id = DraftAccessRequestID:50
      10:53:36,946 INFO com.evergreen.accesscontrol.impl.AccessRequestManager2Bean - conversation.parentId = null
      


      So note that I @Out(ject) the entity to Conversation scope, however, when the link is clicked the second time the SLSB and the SFSB don't have an instance of draftAccessRequestMaster injected. So why can't I find my conversational-scoped entity? It looks like the conversation is correctly @Begin(ning) or joining based on whether or not the conversation exists.

      Thanks,
      Brad Smith