3 Replies Latest reply on Jun 13, 2007 10:09 AM by Pete Muir

    Nested conversation - passing selection to parent conversati

    thatrichard Newbie

      I have a long-running conversation in which the user fills out a form. Some fields are filled by selecting existing objects from the database. The selection is done via a nested conversation.

      The nested conversation starts when the user clicks on a "select" link. The associated method is tagged @Begin(nested=true). The nested conversation ends when the user clicks on a link for the object to be selected. The associated select method is tagged with @End.

      The problem is that since a nested conversation only has readonly access to the parent conversation's context, there doesn't seem to be anyway to get the selection back to the parent conversation.

      I suspect that I am trying to use nested conversations in a way that is not intended.

      Any pointers would be very much appreciated.

      Richard

        • 1. Re: Nested conversation - passing selection to parent conver
          Pete Muir Master

          I don't understand why you are using a nested conversation... Show some code :)

          • 2. Re: Nested conversation - passing selection to parent conver
            thatrichard Newbie

            Trying to answer that question has made me that a nested conversation is in fact not necessary - inappropriate even.

            I've now collapsed the conversations, but the following problem remains - here is the code :)

            The flow is as follows (relevant code in bold)
            1. The Registration form conversation starts with the enterClaim method (first bit of code)
            2. The user clicks a link in the form (not shown) which calls the enterClaimant method on the RegistrationEditorBean. This shows Tab 1 (JSF code below).
            3. The user clicks the select link on that tab, which calls the selectClaimant method on the RegistrationEditorBean. This method creates and installs a PartyFinderClient (more on this soon) and displays the FindPerson Form (JSF code below).
            4. The user searches and the results are shown using the Find Person Results Form (shown below).
            5. The user selects the link for the relevant person and this invokes the select method of PartyFinder (code below)
            6. PartyFinder.select looks up the PartyFinderClient and (i) passes it the selected party so that it can handle the assignment and (ii) redirects to the page specified by that PartyFinderClient. In this case, the PartyFinderClient assigns the party to a field in RegistrationEditor.registrationData and returns to Tab 1.

            (I use PartyFinderClient because there are a number of fields that require the same selection process so the PartyFinderBean cannot know what to do with the data. I'd love to know if there is a more elegant way to do this)

            THE PROBLEM
            When the user makes their selection it all works, except that the RegistrationEditorBean's data field is now null. If I remove the @In(required=false) tag from the setRegistrationData method then this problem disappears - but of course, I need the injection because I might be editing, as opposed, to creating the registrationData. Since I am outjecting the instance of the registrationData, why is that outjected instance not being passed back in?

            Hope you can make sense of all this!

            Richard

            (I'm using method injection as opposed to field injection because, as far as I can see, there is no other way to ensure that nested objects (e.g. submissionInfo) are created on demand)

            RegistrationEditorBean

            ...
            @Name("registrationEditor")
            @Stateful
            @Scope(ScopeType.CONVERSATION)
            @Conversational
            public class RegistrationEditorBean implements RegistrationEditor {
            
             private RegistrationData data;
            
             @In
             private Session session;
            
             @Logger
             private Log log;
            
             @Out
             public RegistrationData getRegistrationData() {
             if (data == null) {data = new RegistrationData(); data.setSubmissionInfo(new SubmissionInfo());}
             return data;
             }
            
             @In(required=false)
             public void setRegistrationData(RegistrationData data) {
             this.data = data;
             }
            
            
             @Begin(flushMode=FlushModeType.MANUAL, join=true)
             public String enterClaim() {
             return "/forms/registration/claim";
             }
            
             public String enterSubmission() {
             return "/forms/registration/submission";
             }
            
             public String enterClaimant() {
             return "/forms/registration/claimant";
             }
            
             public String selectClaimant() {
             PartyFinderClient client = new PartyFinderClient() {
            
             public String cancel() {
             return "/forms/registration/claimant";
             }
            
             public String select(Party party) {
             data.setClaimant(party);
             return "/forms/registration/claimant";
             }
            
             };
             client.install();
             return "/forms/party/find-person";
             }
             ...
            
             public void save() {
             session.save(data.getSubmissionInfo());
             session.save(data);
             session.flush();
             }
            
             ...
             @Destroy @Remove
             public void destroy() { }
            
            }
            



            Registration Form JSF - Tab 1
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE html
             PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns:f="http://java.sun.com/jsf/core"
             xmlns:h="http://java.sun.com/jsf/html"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:s="http://jboss.com/products/seam/taglib"
             xmlns="http://www.w3.org/1999/xhtml">
            <head>
            <title>Registration</title>
            </head>
            <body>
            <ui:composition xmlns:rich="http://richfaces.ajax4jsf.org/rich"
             template="registration.xhtml">
             <ui:define name="tab">
            
             <div name="tabset-actions" />
             <div name="tabset-links">
             <ul class="tabset" />
             </div>
             <div class="tab"><ui:insert name="tab" /></div>
            
            
            
            
             <h:outputLabel value="Claimant" for="claimant" />
             <h:inputText id="claimant"
             value="#{registrationEditor.registrationData.claimant.lastName}"
             readonly="true" />
            
             <h:commandLink id="selectClaimant" value="Select"
             action="#{registrationEditor.selectClaimant}" />
            
            
             </ui:define>
            </ui:composition>
            </body>
            </html>
            
            


            PartyFinderBean
            ...
            @Name("partyFinder")
            @Stateful
            public class PartyFinderBean implements PartyFinder {
            
             @SuppressWarnings("unused")
             @DataModel
             private List<Party> parties;
            
             @DataModelSelection
             private Party selectedParty;
            
             @In
             private Session session;
            
             @Logger
             private Log log;
            
             @SuppressWarnings("unchecked")
             public String find() {
             Party example = new Person();
             Example exampleParty = Example.create(example).ignoreCase().enableLike(MatchMode.ANYWHERE);
             parties = session.createCriteria(Person.class)
             .add(exampleParty)
             .list();
             return "/forms/party/findPartyResults";
            
             }
            
             public String cancel() {
             PartyFinderClient client = PartyFinderClient.getInstalled();
             return (client == null ? null : client.cancel());
             }
            
             public String select() {
             PartyFinderClient client = PartyFinderClient.getInstalled();
             return (client == null ? null : client.select(selectedParty));
             }
            
             @Remove @Destroy
             public void destroy() { }
            
            }
            


            PartyFinderClient
            ...
            public abstract class PartyFinderClient {
            
             public void install() {
             Contexts.getConversationContext().set("partyFinderClient", this);
             }
            
             public static PartyFinderClient getInstalled() {
            
             return (PartyFinderClient) Contexts.getConversationContext(). get("partyFinderClient");
             }
            
             public abstract String cancel();
             public abstract String select(Party party);
            }
            
            

            Find Person Form JSF
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE html
             PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:s="http://jboss.com/products/seam/taglib"
             xmlns="http://www.w3.org/1999/xhtml">
             <head>
             <title>Find Person</title>
             </head>
             <body>
             <ui:composition xmlns:rich="http://richfaces.ajax4jsf.org/rich" template="/layout/template.xhtml">
             <ui:define name="body">
             <h:form id="form">
            
            
            
            
             <h:outputLabel value="Last Names" for="lastName"/>
             <h:inputText id="lastName" value="#{lastName}"/>
             <h:outputLabel value="First Name(s)" for="firstNames"/>
             <h:inputText id="firstNames" value="#{firstName}"/>
             <h:outputLabel value="Date of Birth" for="dateOfBirth"/>
             <h:inputText id="dateOfBirth" value="#{dateOfBirth}"/>
             <h:outputLabel value="Identity No." for="identityNo"/>
             <h:inputText id="identityNo" value="#{identityNo}"/>
             <h:outputLabel value="Passport No." for="passportNo"/>
             <h:inputText id="passportNo" value="#{passportNo}"/>
             <h:outputLabel value="Bank Account No." for="bankAccountNo"/>
             <h:inputText id="bankAccountNo" value="#{bankAccountNo}"/>
             <h:commandButton id="find" value="Find" action="#{partyFinder.find}"/>
             <h:commandLink id="clear" value="Clear" action="doClear"/>
            
            
             </h:form>
             </ui:define>
             </ui:composition>
             </body>
            </html>
            


            Find Person Results
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE html
             PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:s="http://jboss.com/products/seam/taglib"
             xmlns="http://www.w3.org/1999/xhtml">
             <head>
             <title>Find Party Results</title>
             </head>
             <body>
             <ui:composition xmlns:rich="http://richfaces.ajax4jsf.org/rich" template="/layout/template.xhtml">
             <ui:define name="body">
             <h:form id="form">
            
            
            
            
             <h:dataTable value="#{parties}" rendered="#{parties.rowCount>0}" var="party">
             <h:column>
             <f:facet name="header">
             <h:outputText value="Last Name"/>
             </f:facet>
             <s:link value="#{party.lastName}" action="#{partyFinder.select}"/>
             </h:column>
             </h:dataTable>
            
            
             </h:form>
             </ui:define>
             </ui:composition>
             </body>
            </html>
            


            • 3. Re: Nested conversation - passing selection to parent conver
              Pete Muir Master

              Try using @In(create=true) and a @Factory to instantiate missing objects. This will allow you to use field injection as well.