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 :-(