Conversations - do not work in Seam 1.2.1?
bsmithjj Jun 13, 2007 11:17 AMI'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