6 Replies Latest reply on Aug 8, 2008 10:08 PM by infinity2heaven

    how to pass variables between 2 SFSBs

    infinity2heaven Novice

      I have two SFSB's A and B (pretty simple). I need to call B.foo(variableB) from A.


      @In(create=true)  @Out(required=false)   
      private xxx variableB;



      I have a redirect in my pages.xml and B.foo does get called. However the variableB is not initialized to the value I passed from A. Because both are conversation scoped by default, I'd imagine that the moment SFSB B is called, the values from older conversation is not accessible here.


      I read a lot about nested conversations and making variableB as  @out(scope=SessionScope)
      but I'm not sure whats the correct way to implement this.


      Any pointers?


      The idea is to freely navigate to/from multiple session beans with variables being passed.

        • 1. Re: how to pass variables between 2 SFSBs
          System Administrator Expert

          This is most definitely doable.  Post the implementation classes for the two session beans.  Otherwise, check out the booking example or other Seam distro examples.  this is a very common activity in Seam code.

          • 2. Re: how to pass variables between 2 SFSBs
            infinity2heaven Novice

            I'm implementing basic CRUD screens but with some sophisticated UI layouts.  EntityHome is full of bugs, doesn't work for all. So here is my code


            @Stateful
            @Name(value = "fofAdmin")
            public class FofAdminAction extends EntityController implements FofAdmin {
            
                 static Log log = LogFactory.getLog(FofAdminAction.class.getName());
            
                 @In(create = true)
                 @Out(required = false)
                 private Fof selectedFof;
            
                 @In(create = true)
                 private FundAdmin fundAdmin;
            
                 public void view(Fof viewFof) {
                      log.debug("viewing fof - " + viewFof);
                      selectedFof = viewFof;
                 }
            
                 public void add() {
                      // clear the existing fof
                      selectedFof = new Fof();
                 }
            
                 public void save() {
                      persist(selectedFof);
                      addFacesMessage(ASRUtils.displayCrudMessage("save"));
                 }
            
                 public void delete() {
                      remove(selectedFof);
                      addFacesMessage(ASRUtils.displayCrudMessage("delete"));
                 }
            
                 public void update() {
                      merge(selectedFof);
                      addFacesMessage(ASRUtils.displayCrudMessage("update"));
                 }
            
                 @Factory(value = "selectedFof")
                 public Fof initSelectedFof() {
                      return new Fof();
                 }
                 
                 public void switchToFundAdmin(Fund fund) {
                      log.debug("Switching to Fund Admin for fund - " + fund);
                      fundAdmin.view(fund);
                 }
            
                 @Remove
                 @Destroy
                 public void destroy() {
                      log.debug("FofAdminAction: destroy ...");
                 }
            }



            The other one is 95% identical



            @Stateful
            @Name(value = "fundAdmin")
            public class FundAdminAction extends EntityController implements FundAdmin {
            
                 static Log log = LogFactory.getLog(FundAdminAction.class.getName());
            
                 @In(create = true)
                 @Out(required = false)
                 private Fund selectedFund;
            
                 @In(create = true)
                 private FofAdmin fofAdmin;
            
                 public void view(Fund viewFund) {
                      log.debug("viewing fund - " + viewFund.getName());
                      selectedFund = viewFund;
                 }
            
                 public void add() {
                      // clear the existing fund
                      selectedFund = new Fund();
                 }
            
                 public void save() {
                      persist(selectedFund);
                      addFacesMessage(ASRUtils.displayCrudMessage("save"));
                 }
            
                 public void delete() {
                      remove(selectedFund);
                      selectedFund = new Fund();
                      addFacesMessage(ASRUtils.displayCrudMessage("delete"));
                 }
            
                 public void update() {
                      merge(selectedFund);
                      addFacesMessage(ASRUtils.displayCrudMessage("update"));
                 }
            
                 @Factory(value = "selectedFund")
                 public Fund initSelectedFund() {
                      return new Fund();
                 }
            
                 public void addAlias() {
                      selectedFund.addAlias(new FundAlias());
                 }
            
                 public void removeAlias(FundAlias alias) {
                      selectedFund.removeAlias(alias);
                 }
            
                 public void switchToFofAdmin(Fof fof) {
                      log.debug("Swithcing to Fof Admin");
                      fofAdmin.view(fof);
                 }
            
                 @Remove
                 @Destroy
                 public void destroy() {
                      log.debug("FundAdminAction: destroy ...");
                 }
            }



            I need to call switchToXXXAdmin from either SFSB, the problem is, the xxx variable is always shown as null when



            pages.xml


            <page view-id="/fundAdmin.xhtml">     
                 <navigation from-action="#{fundAdmin.view(fund)}">          
                    <begin-conversation join="true"/>                           
                 </navigation>  
                 <navigation from-action="#{fundAdmin.save || fundAdmin.update || fundAdmin.delete}">    
                     <end-conversation/>      
                 </navigation> 
                 <navigation from-action="#{fundAdmin.switchToFofAdmin(fof)}">    
                    <redirect view-id="/fofAdmin.xhtml"/>
                 </navigation>      
              </page>
              
              <page view-id="/fofAdmin.xhtml">     
                  <navigation from-action="#{fofAdmin.view(fof)}">          
                    <begin-conversation join="true"/>                           
                  </navigation>  
                  <navigation from-action="#{fofAdmin.save || fofAdmin.update || fofAdmin.delete}">    
                     <end-conversation/>      
                  </navigation>   
                  <navigation from-action="#{fodAdmin.switchToFundAdmin(fund)}">    
                    <redirect view-id="/fundAdmin.xhtml"/>
                 </navigation>      
              </page>




            I've seen booking example, I dont recollect the above requirement though

            • 3. Re: how to pass variables between 2 SFSBs
              System Administrator Expert

              Here is a working example of what you asked for.  I modified the booking example (see find() method) to call a public method on an injected SFSB with a String param passed.  Default context for a SFSB is conversation scope.  enjoy.


              HotelSearchingAction.java


              package org.jboss.seam.example.booking;
              
              import java.util.List;
              
              import javax.ejb.Remove;
              import javax.ejb.Stateful;
              import javax.persistence.EntityManager;
              import javax.persistence.PersistenceContext;
              
              import org.jboss.seam.ScopeType;
              import org.jboss.seam.annotations.Factory;
              import org.jboss.seam.annotations.In;
              import org.jboss.seam.annotations.Name;
              import org.jboss.seam.annotations.Scope;
              import org.jboss.seam.annotations.datamodel.DataModel;
              import org.jboss.seam.annotations.security.Restrict;
              
              @Stateful
              @Name("hotelSearch")
              //@Scope(ScopeType.SESSION)
              @Restrict("#{identity.loggedIn}")
              public class HotelSearchingAction implements HotelSearching
              {
                 
                 @PersistenceContext
                 private EntityManager em;
                 
                 private String searchString;
                 private int pageSize = 10;
                 private int page;
                 
                 @DataModel
                 private List<Hotel> hotels;
                 
                 @In(create=true)
                 private TestLocal testAction;
                 
                 public void find()
                 {
                    page = 0;
                    queryHotels();
                    
                    //exec method on injected SFSB
                    testAction.calculate("100");
                 }
                 public void nextPage()
                 {
                    page++;
                    queryHotels();
                 }
                    
                 private void queryHotels()
                 {
                    hotels = em.createQuery("select h from Hotel h where lower(h.name) like #{pattern} or lower(h.city) like #{pattern} or lower(h.zip) like #{pattern} or lower(h.address) like #{pattern}")
                          .setMaxResults(pageSize)
                          .setFirstResult( page * pageSize )
                          .getResultList();
                 }
                 
                 public boolean isNextPageAvailable()
                 {
                    return hotels!=null && hotels.size()==pageSize;
                 }
                 
                 public int getPageSize() {
                    return pageSize;
                 }
                 
                 public void setPageSize(int pageSize) {
                    this.pageSize = pageSize;
                 }
                 
                 @Factory(value="pattern", scope=ScopeType.EVENT)
                 public String getSearchPattern()
                 {
                    return searchString==null ? 
                          "%" : '%' + searchString.toLowerCase().replace('*', '%') + '%';
                 }
                 
                 public String getSearchString()
                 {
                    return searchString;
                 }
                 
                 public void setSearchString(String searchString)
                 {
                    this.searchString = searchString;
                 }
                 
                 @Remove
                 public void destroy() {}
              }



              TestAction.java (new action class I created):


              //$Id: HotelSearchingAction.java 5579 2007-06-27 00:06:49Z gavin $
              package org.jboss.seam.example.booking;
              
              import javax.ejb.Remove;
              import javax.ejb.Stateful;
              
              import org.jboss.seam.ScopeType;
              import org.jboss.seam.annotations.Logger;
              import org.jboss.seam.annotations.Name;
              import org.jboss.seam.annotations.Scope;
              import org.jboss.seam.annotations.security.Restrict;
              import org.jboss.seam.log.Log;
              
              @Stateful
              @Name("testAction")
              @Scope(ScopeType.CONVERSATION)
              @Restrict("#{identity.loggedIn}")
              public class TestAction implements TestLocal
              {
                 
                 private String dollars;
                 
                 @Logger
                 Log log;
                   
                 public void calculate(String dollars) {
                      this.dollars = dollars;
                      log.info("dollars = "+dollars);
                 }
                 
                 @Remove
                 public void destroy() {}
              }

              • 4. Re: how to pass variables between 2 SFSBs
                Pete Muir Master

                Priya M wrote on Aug 08, 2008 03:13:

                EntityHome is full of bugs, doesn't work for all.


                What bugs, where are the JIRAs?

                • 5. Re: how to pass variables between 2 SFSBs
                  infinity2heaven Novice

                  Sorry, my bad. I obviously know how this works.The problem was something else  --


                  I used <s:link action="#{sfsb.someMethod(variableB)}" />


                  and s:link doesnt pass variableB to server side, hence it was never being passed in the first place. I'm using <h:commandLink instead, which now passed the variable.

                  • 6. Re: how to pass variables between 2 SFSBs
                    infinity2heaven Novice

                    I wanted to raise a JIRA but - I dont know what the problem is! It just doesn't update. (create delete works). A couple of my colleagues had the same problem and no idea what the reason could be. The examples and docs are pretty st fwd too. Besides, extending EntityController I can still write minimal code. I  saw the source code for EntityHome, it doesn't do much except for join transactions (which are already present) and raise events (which I dont need for now).