7 Replies Latest reply on Feb 4, 2008 4:37 PM by Guillaume Jeudy

    Trinidad SelectManyShuttle with seam ?

    Guillaume Jeudy Master

      Hi,

      I'm trying to use a selectManyShuttle trinidad component with seam. The problem I have is I can't get the selected entries from my backing bean because they were just populated on the client side. How should I go about this ?

      I need a way to post the selected entries for seam to process and inject in my seam component.

      Has anyone tried the same thing before?

      Below is a small code snippet, I can display the component successfully and select items from it but I can't use the selected items anywhere.

      <tr:selectManyShuttle id="existitemshuttle2"
       leadingHeader="Domain Objects Found" trailingHeader="Domain Objects Selected"
       value="#{refDomainSearch.selectedRefDomains}" size="#{refDomainSearch.pageSize}" rendered="#{not empty refDomainSearch.refDomains}">
       <s:selectItems var="refDomain" label="#{refDomain.domainName}" value="#{refDomainSearch.refDomains}">
       </s:selectItems>
       <s:convertEntity />
       </tr:selectManyShuttle>


      Thanks,
      -Guillaume

        • 1. Re: Trinidad SelectManyShuttle with seam ?
          Guillaume Jeudy Master

          I was thinking perhaps I could leverage the Seam Remoting capabilities.

          Once I selected the items I need, I press a command button

          <s:commandButton action="#{mybackingbean.process}" onclick="setSelection()" />


          I implement a setSelection() javascript function that retrieves the selection from the trinidad component and submits it through seam remoting capabilities. The only bummer with this is I need the AJAX call to be synchronous (SJAX) to make sure that when the action on the command button is processed I already have updated the server state with the selected items.

          Is it possible to use Seam remoting synchronously ? I know this is generally a bad thing to do but in my case it would help me solve my problem.


          Thanks,
          -Guillaume

          • 2. Re: Trinidad SelectManyShuttle with seam ?
            Guillaume Jeudy Master

            Alternatively has anyone used a different JSF library that has a dual list component with SEAM successfully ? I see JBoss RichFaces has a ListShuttle which seems to be what I need. Has anyone used this with seam ?

            Thanks,
            -Guillaume

            • 3. Re: Trinidad SelectManyShuttle with seam ?
              Pete Muir Master

              I'm not really understanding your problem. When you submit the form, the selection should be set on your bound bean. I.e. this should "just work"

              • 4. Re: Trinidad SelectManyShuttle with seam ?
                Guillaume Jeudy Master

                Apologies, I am new to facelets/JSF and didn't realize exactly how the binding to the backing bean to my commandButton occurs. The commandButton was not inside the same form that contained the selectManyShuttle component. Now it works as expected, thanks.

                PS: On a related note, I am using trinidad/ajax4jsf/facelets/myfaces/seam combination.

                Would anyone recommend me to switch to richfaces/facelets/myfaces/seam combination ? Has anyone made successful use of richfaces and the ListShuffle component in a SEAM project?

                At least by looking at the user doc; richfaces seems like a compelling choice and probably provides just as much if not more than trinidad/ajax4jsf.

                Thanks,
                -Guillaume

                • 5. Re: Trinidad SelectManyShuttle with seam ?
                  Guillaume Jeudy Master

                  I tought trinidad SelectManyShuttle was working. Actually I always get the same value in my selected list which is always the first value of the available list no matter what I put in my selected list(on the client side). This happens when executing the action on the command button on the server side.

                  In the code example below, it's the first value in
                  #{refDomainSearch.refDomains}, how come #{refDomainSearch.selectedRefDomains} always contain this first value ?

                  Could this be a bug in trinidad component library or a problem with trinidad/seam integration ?

                  refDomainSearch is a stateful bean/seam managed component with session scope and getters/setters for refDomains & selectedRefDomains. I don't use @In/@Out annotation in my example.

                  <tr:selectManyShuttle id="existitemshuttle2"
                   leadingHeader="Domain Objects Found" trailingHeader="Domain Objects Selected"
                   value="#{refDomainSearch.selectedRefDomains}" size="#{refDomainSearch.pageSize}" rendered="#{not empty refDomainSearch.refDomains}">
                   <s:selectItems var="refDomain" label="#{refDomain.domainName}" value="#{refDomainSearch.refDomains}">
                   </s:selectItems>
                   <s:convertEntity />
                   </tr:selectManyShuttle>


                  The commandButton triggering the action is part of the same form.

                  <h:commandButton type="submit" value="Add selection to package"
                   action="#{refDomainSearch.updatePackageItems}" />


                  Thanks,
                  -Guillaume

                  • 6. Re: Trinidad SelectManyShuttle with seam ?
                    Pete Muir Master

                    Lets see the backing bean.

                    You can use RichFaces and Trinidad together btw.

                    • 7. Re: Trinidad SelectManyShuttle with seam ?
                      Guillaume Jeudy Master

                      Yes I figured later you can use both trinidad and richfaces.

                      I switched to rich:listShuttle component which did not require me any extra coding, I just kept using the same backing bean. The rich:listShuttle works as expected, I had to add the seam entity converter in converter attribute though,

                      converter="#{org.jboss.seam.ui.entityConverter}"


                      Below is the backing bean code in case you still want to look at it.

                      package a.b.c;
                      
                      import java.text.ParseException;
                      import java.util.Calendar;
                      import java.util.Date;
                      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.Destroy;
                      import org.jboss.seam.annotations.Factory;
                      import org.jboss.seam.annotations.In;
                      import org.jboss.seam.annotations.Logger;
                      import org.jboss.seam.annotations.Name;
                      import org.jboss.seam.annotations.Out;
                      import org.jboss.seam.annotations.Scope;
                      import org.jboss.seam.core.FacesMessages;
                      import org.jboss.seam.log.Log;
                      
                      import a.b.c.d.RefReleasePackage;
                      import a.b.c.d.e.RefReleasePackageItemImpl;
                      import a.b.c.d.ReferenceDomain;
                      import a.b.c.d.e.RefDomainSearchActionLocal;
                      import a.b.c.d.ReleasePackageService;
                      import a.b.c.d.CommonUtils;
                      import a.b.c.d.RDMConstants;
                      
                      @Stateful
                      @Name("refDomainSearch")
                      @Scope(ScopeType.SESSION)
                      public class RefDomainSearchActionBean implements RefDomainSearchActionLocal {
                      
                       @PersistenceContext(unitName = RDMConstants.RDM_PERSISTENCE_UNIT_NAME)
                       private EntityManager em;
                      
                       @Logger
                       private Log log;
                      
                       private String searchString;
                       private int pageSize;
                       private int page;
                      
                       private List<ReferenceDomain> refDomains;
                      
                       private List<ReferenceDomain> selectedRefDomains;
                      
                      
                       @In(required = true, create=true)
                       @Out(required = true, scope = ScopeType.SESSION)
                       private ReleasePackageService releasePackageService;
                      
                       @In(required = false)
                       @Out(required = false)
                       private RefReleasePackage relPkg;
                      
                       public void find() {
                       page = 0;
                       queryRefDomains();
                       }
                      
                       public void nextPage() {
                       page++;
                       queryRefDomains();
                       }
                      
                       public boolean isNextPageAvailable() {
                       return refDomains != null && refDomains.size() == pageSize;
                       }
                      
                       /**
                       * TODO Could write this HQL using Criteria programming model instead.
                       * Then you get compile time validation of the query.
                       */
                       @SuppressWarnings("unchecked")
                       public void queryRefDomains() {
                      
                       // TODO optimize the fetching takes around 25 secs today.
                       refDomains = em.createQuery(
                       "select rd from ReferenceDomainImpl rd " +
                       "where lower(rd.domainName) like #{pattern} or lower(rd.domainDescription) like #{pattern} " +
                       "or exists ( from ReferenceDomainInstanceImpl rdi " +
                       "where rdi.referenceDomain.id = rd.id " +
                       "and " +
                       "(lower(rdi.codeValue) like #{pattern} " +
                       "or lower(rdi.shortDescription) like #{pattern} " +
                       "or lower(rdi.description) like #{pattern}))" +
                       "order by rd.domainName")
                       .setMaxResults(pageSize).setFirstResult(page * pageSize).getResultList();
                       }
                      
                       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;
                       }
                      
                      
                       public List<ReferenceDomain> getRefDomains() {
                       return refDomains;
                       }
                      
                       public List<ReferenceDomain> getSelectedRefDomains() {
                       return selectedRefDomains;
                       }
                      
                       public void setSelectedRefDomains(List<ReferenceDomain> selectedRefDomains) {
                       this.selectedRefDomains = selectedRefDomains;
                       }
                      
                       /**
                       * TODO remove from bean, just added for tests.
                       * @return
                       */
                       public String updatePackageItems() {
                       log.info("Inside ReleasePackageAction.updatePackageItems");
                      
                       Date toDate = null;
                       try {
                       toDate = CommonUtils.getSQLDateFromString(RDMConstants.DEFAULT_VALID_TO_DT);
                       } catch (ParseException pe) {
                       throw new RuntimeException(pe);
                       }
                      
                       for (ReferenceDomain refDomain : selectedRefDomains) {
                       RefReleasePackageItemImpl item = new RefReleasePackageItemImpl(refDomain, relPkg, Calendar.getInstance().getTime(), toDate);
                      
                       relPkg.addRefReleasePackageItem(item);
                       }
                       selectedRefDomains.clear();
                       relPkg = releasePackageService.updateReleasePackage(relPkg);
                       FacesMessages.instance().add("Release Package: #{relPkg.releasePackageNm} is successfully updated");
                       return "/editPackageItems.seam";
                       }
                      
                       @Destroy
                       @Remove
                       public void destroy() {
                       }
                      }


                      Thanks,
                      -Guillaume