4 Replies Latest reply on Jul 27, 2006 1:05 PM by krypton

    Outjection of previous value: selectOneMenu : One 2 Many Rel

    krypton Novice

      JBoss 4.0.4.GA
      JBoss Seam 1.0.1 GA

      Hi, I am really stuck and cant progress :-(
      I have a page called viewRatePage, which allows
      users to add Rate objects to their profile. When
      I add a new rate, the selectOneMenu items never
      clear on the refresh when a new rate is added,
      it contains the old selection of the previous
      rate. I do force a null on the injected rate, but
      this has no effect. Please please can anyone help?
      This issue affects other pages which have the same
      relationship, ie adding items to a list.

      These are my previous posts:
      http://www.jboss.com/index.html?module=bb&op=viewtopic&t=87408

      This is my view:

      <div class="section">
       <fieldset>
      
       <div class="entry_small">
      
       <c:choose>
       <c:when test='${ratesPageManager.rates == null or ratesPageManager.rowCount == 0}'>
       Empty Rates
       </c:when>
       <c:otherwise>
       <h:dataTable value="#{ratesPageManager.rates}" var="item" rendered="#{ratesPageManager.rowCount>0}" rowClasses="rvgRowOne,rvgRowTwo">
      
       <h:column>
       <f:facet name="header"><h:outputText value="Duration"/></f:facet>
       <h:outputText value="#{item.duration}"/>
       </h:column>
       <h:column>
       <f:facet name="header"><h:outputText value="Unit"/></f:facet>
       <h:outputText value="#{item.unit}"/>
       </h:column>
       <h:column>
       <f:facet name="header"><h:outputText value="Currency"/></f:facet>
       <h:outputText value="#{item.currency}"/>
       </h:column>
       <h:column>
       <f:facet name="header"><h:outputText value="Cost"/></f:facet>
       <h:outputText value="#{item.cost}"/>
       </h:column>
       <h:column>
       <f:facet name="header">Action</f:facet>
       <h:commandLink action="#{ratesPageManager.deleteRate}">Delete</h:commandLink>
       </h:column>
      
       </h:dataTable>
       </c:otherwise>
       </c:choose>
      
       </div>
       </fieldset>
      
       <br/>
       <fieldset>
       <div class="entry_small">
       <h:form>
       <table>
       <tr>
       <td><div class="label"><h:outputLabel>Duration:</h:outputLabel></div></td>
       <td><div class="select"><h:selectOneMenu value="#{rate.duration}"><f:selectItems value="#{ratesManager.durations}"/></h:selectOneMenu></div></td>
       <td><div class="label"><h:outputLabel>Unit:</h:outputLabel></div></td>
       <td><div class="select"><h:selectOneMenu value="#{rate.unit}"><f:selectItems value="#{ratesManager.units}"/></h:selectOneMenu></div></td>
       <td><div class="label"><h:outputLabel>Currency:</h:outputLabel></div></td>
       <td><div class="select"><h:selectOneMenu value="#{rate.currency}"><f:selectItems value="#{ratesManager.currencys}"/></h:selectOneMenu></div></td>
       <td><div class="label"><h:outputLabel>Cost:</h:outputLabel></div></td>
       <td><div class="select"><h:selectOneMenu value="#{rate.cost}"><f:selectItems value="#{ratesManager.costs}"/></h:selectOneMenu></div></td>
       </tr>
       <tr>
       <td colspan="8">
       <h:commandButton value="Add Rate" action="#{ratesPageManager.addRate}" class="button"/>
       </td>
       </tr>
       </table>
       </h:form>
       </div>
       </fieldset>
       </div>
      


      Any my Rate object that gets instantiated is an entity bean:

      @Entity
      @Name("rate")
      @Scope(EVENT)
      public class Rate implements Serializable {
      
       protected int Id = 0;
      
       protected int duration = 0;
       protected String unit = null;
       protected String currency = null;
       protected int cost = 0;
       protected RatesPage ratesPage = null;
      
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       public int getId() {
       return Id;
       }
      
       public void setId(int id) {
       Id = id;
       }
       ... // for brevity
      


      My session bean behind the page is (with unnecessary methods removed):

      @Stateful
      @Scope(ScopeType.SESSION)
      @Name("ratesPageManager")
      @Interceptors(SeamInterceptor.class)
      @LoggedIn
      @TransactionAttribute(REQUIRES_NEW)
      public class RatesPageManagerBean implements RatesPageManager {
      
       @In
       @Out
       @Valid
       private User user;
      
       @In
       @Out
       @Valid
       private Profile profile;
      
       @In(required = false)
       @Out(required = false)
       @Valid
       private RatesPage ratesPage;
      
       @PersistenceContext
       private EntityManager em;
      
       @In
       private transient FacesContext facesContext;
      
       @DataModel
       private List<Rate> rates = new ArrayList();
      
      
       @DataModelSelection
       private Rate selectedRate;
      
       @In(required = false)
       private Rate rate;
      
      
       //public Rate getRate() {
       // return newRate;
       //}
      
       // public void setRate(Rate rate) {
       // this.newRate = rate;
       // }
      
      
      
       @IfInvalid(outcome = REDISPLAY)
       public String create() {
       if (profile.getRatesPage() == null) {
       em.persist(ratesPage);
       profile.setRatesPage(ratesPage);
       profile = em.merge(profile);
       ratesPage = em.merge(ratesPage);
       em.refresh(user);
       return "viewRatesPage";
       } else {
       facesContext.addMessage(null, new FacesMessage("RatesPage already exists"));
       return "viewProfile";
       }
       }
      
       public String select() {
       profile = user.getProfile();
       ratesPage = profile.getRatesPage();
       rates.clear();
       rates.addAll(ratesPage.getRates());
       clearRatesOnDisplay();
       return "viewRatesPage";
       }
      
       private boolean isUnSet(Rate rateToCheck) {
      
       boolean isOk = (
       (rateToCheck.getCost() == 0) || (rateToCheck.getCurrency().equals("-")) ||
       (rateToCheck.getDuration() == 0) || (rateToCheck.getUnit().equals("-"))
       );
       log.info("Rate check:: cost=" + rateToCheck.getCost() + " currency=" +rateToCheck.getCurrency()
       + " duration=" + rateToCheck.getDuration() + " unit=" + rateToCheck.getUnit());
       return isOk;
       }
      
      
       public String addRate() {
       log.info("addRate() called - " + rate);
      
       if(isUnSet(rate)) {
       log.warn("Failed rates check");
       rate = null;
       facesContext.addMessage(null, new FacesMessage("Please enter rates"));
       return "viewRatesPage";
       }
       log.info("trying to add rate - " + rate);
       rate.setRatesPage(ratesPage);
       em.persist(rate);
       ratesPage.addRate(rate);
       ratesPage = em.merge(ratesPage);
       profile = em.merge(profile);
       log.info("Persisted! and trying to remove");
       clearRatesOnDisplay();
       return select();
       }
      
       public String deleteRate() {
       log.info("deleteRate() called, removing " + selectedRate);
       rates.remove(selectedRate);
       ratesPage.removeRate(selectedRate);
       em.remove(selectedRate);
       clearRatesOnDisplay();
       return "viewRatesPage";
       }
      
       public String delete() {
       profile.setRatesPage(null);
       em.remove(ratesPage);
       profile = em.merge(profile);
       ratesPage = null;
       return "viewProfile";
       }
      
       private void clearRatesOnDisplay() {
       Contexts.getPageContext().remove("rate");
       //Contexts.getPageContext().remove("ratesManager");
       rate = null;
       selectedRate = null;
       }
      }
      


      The component/javabean that provides the rate types and values is
      @Name("ratesManager")
      @Interceptors(SeamInterceptor.class)
      @Scope(ScopeType.APPLICATION)
      public class Rates {
      
       public Rates() {
       log.info("** Rates (RatesManager) instantated **");
       }
      
       /**
       * The durations
       */
       static final String[][] DURATION = // left out for brevity
      
       /**
       * The units
       */
       static final String[][] UNIT = // left out for brevity
      
       /**
       * The currency
       */
       static final String[][] CURRENCY = // left out for brevity
      
       /**
       * The cost
       */
       static final String[][] COST = // left out for brevity
      
       /**
       * The duration list
       *
       * @return List
       */
       public List<SelectItem> getDurations() {
       List<SelectItem> result = new ArrayList<SelectItem>();
       for (int i = 0; i < DURATION.length; i++) { // value, label, desc
       result.add(new SelectItem(DURATION[0], DURATION[1], DURATION[2]));
       }
       return result;
       }
      
       /**
       * The unit list
       *
       * @return List
       */
       public List<SelectItem> getUnits() {
       List<SelectItem> result = new ArrayList<SelectItem>();
       for (int i = 0; i < UNIT.length; i++) { // value, label, desc
       result.add(new SelectItem(UNIT[0], UNIT[1], UNIT[2]));
       }
       return result;
       }
      
       /**
       * The currency list
       *
       * @return List
       */
       public List<SelectItem> getCurrencys() {
       List<SelectItem> result = new ArrayList<SelectItem>();
       for (int i = 0; i < CURRENCY.length; i++) { // value, label, desc
       result.add(new SelectItem(CURRENCY[0], CURRENCY[1], CURRENCY[2]));
       }
       return result;
       }
      
       /**
       * The cost list
       *
       * @return List
       */
       public List<SelectItem> getCosts() {
       List<SelectItem> result = new ArrayList<SelectItem>();
       for (int i = 0; i < COST.length; i++) { // value, label, desc
       result.add(new SelectItem(COST[0], COST[1], COST[2]));
       }
       return result;
       }
      
      
      }
      


      Upon inserting the first rate, the view still shows the previous rate in the selectMenus, if you
      change it and reinsert, the following exception is thrown

      20:32:37,698 ERROR [STDERR] Jul 26, 2006 8:32:37 PM com.sun.facelets.FaceletViewHandler handleRenderException
      SEVERE: Error Rendering View
      java.lang.IllegalStateException: Client-id : _id0 is duplicated in the faces tree.
       at org.apache.myfaces.application.jsp.JspStateManagerImpl.checkForDuplicateIds(JspStateManagerImpl.java:241)
       at org.apache.myfaces.application.jsp.JspStateManagerImpl.checkForDuplicateIds(JspStateManagerImpl.java:255)
       at org.apache.myfaces.application.jsp.JspStateManagerImpl.saveSerializedView(JspStateManagerImpl.java:204)
       at org.jboss.seam.jsf.SeamStateManager.saveSerializedView(SeamStateManager.java:46)
       at com.sun.facelets.FaceletViewHandler.writeState(FaceletViewHandler.java:589)
       at org.apache.myfaces.renderkit.html.HtmlFormRendererBase.encodeBegin(HtmlFormRendererBase.java:74)
       at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:307)
       at com.sun.facelets.FaceletViewHandler.encodeRecursive(FaceletViewHandler.java:511)
       at com.sun.facelets.FaceletViewHandler.encodeRecursive(FaceletViewHandler.java:518)
       at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:447)
       at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:352)
       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:107)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.apache.myfaces.component.html.util.ExtensionsFilter.doFilter(ExtensionsFilter.java:92)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.apache.myfaces.component.html.util.ExtensionsFilter.doFilter(ExtensionsFilter.java:122)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.seam.servlet.SeamRedirectFilter.doFilter(SeamRedirectFilter.java:30)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
       at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
       at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
       at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
       at java.lang.Thread.run(Thread.java:595)
      20:32:37,700 ERROR [STDERR] Jul 26, 2006 8:32:37 PM com.sun.facelets.FaceletViewHandler handleRenderException
      SEVERE: Took Type: java.io.PrintWriter
      20:32:37,717 INFO [RatesPageManagerBean] getRates() called size = 1
      


      The server debug log shows that the previous rate object is passed down.

      I tried modifiying the messages example with no success as the input field in the view
      still had the old inserted value, see previous thread i mentioned.

      Any ideas people ... i tried formatting this properly to get some help about this :-(