Outjection of previous value: selectOneMenu : One 2 Many Rel
kryptontri Jul 26, 2006 3:33 PMJBoss 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 :-(