Hi,
i have a web application running in the following environment:
JBoss 4.2.2
myfaces 1.1.5
jsf-facelets 1.1.13
trinidad 1.0.11
I have 2 different enum types:
Enum1 {A, B}
Enum2 {A1, A2, A3, B1, B2}
And I have 2
<tr:selectOneListbox><http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_selectOneListbox.html>
(also tested with
<tr:selectOneChoice><http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_selectOneChoice.html>,
same effects):
<tr:selectOneListbox
id="selection1"
label="selection1"
value="#{selected1}"
immediate="true"
required="false"
autoSubmit="true" >
<f:selectItems value="#{enum1values" />
<f:valueChangeListener
type="de.tccproducts.Enum1ValueChanged " />
</tr:selectOneListbox>
<tr:selectOneListbox
id="selection2"
label="selection2"
value="#{selected2}"
required="true"
partialTriggers="selection1">
<f:selectItems value="#{enum2values}" />
</tr:selectOneListbox>
enum1values is a Map of String and the values of Enum1
enum2values is null at the beginning and gets changed by the valueChangeListener
The ValueChangeListener does the following:
- when event.newValue is null, selectedEnumValues = null AND selected2
= null
- when event.newValue is Enum1.A, selectedEnumValues = Map of String
and values of Enum2 (A1, A2, A3) AND selected2 = null
- when event.newValue is Enum1.B, selectedEnumValues = Map of String
and values of Enum2 (B1, B2) AND selected2 = null
Now to my first problem:
If I select A in the first listbox, than select A1 in the second listbox, than
select B in the first listbox, the value B1 is selected in the second listbox.
Looks like the selected2 = null is not used, the component remembers that index
1 is selected, and so the "new" item on index 1 is selected.
This is getting worse if I do the following:
Select A in the first listbox, than select A3 in the second listbox, than
select B in the first listbox
The second listbox still "remember" that index 3 was selected, but there are
only 2 selectable values, causing an ArrayIndexOutOfBounceException in Trinidad
code (See below: StackTrace1)
Is this an trinidad bug or something general with the JSF livecycle I'm missing?
To work around this I have changed the second listbox to have
valuePassThru="true"
and use a custom converter
<dps:enumConverter type="de.tccproducts.Enum2" />
The EnumConverter is initizied with the full qualified class name of the enum.
In the getAsString it simply returns paramObject.toString();
In the getAsObject it returns Enum.valueOf(type, paramsString) to get the
EnumInsttance for the given String
(for SourceCode see below:EnumConverterSource)
The converter is registered in the facesConfig.xml:
<converter>
<converter-id>tccEntityConverter</converter-id>
<converter-class>de.tccproducts.dps.web.utils.converter.EntityConverter</converter-class>
<property>
<property-name>type</property-name>
<property-class>java.lang.Class</property-class>
</property>
</converter>
And the tag for the converter is registered in the facelets tag lib:
<tag>
<tag-name>enumConverter</tag-name>
<converter>
<converter-id>tccEnumConverter</converter-id>
</converter>
</tag>
This all works as wanted and no more index out of bounce exceptions are
occurring, but when Trinidad updates the listbox in the ppr, always this log
message occurs:
Time
Thread
Level
Category
Message
612234
http-0.0.0.0-8080-2
ERROR
org.apache.myfaces.application.ApplicationImpl
Initializing converter : de.tccproducts.dps.web.utils.converter.EnumConverter
with property : type and value : null failed.
So looks like the converter is not initialized correctly, but it is working
correctly, type is set, no Null pointer occurs.
So what's the problem with this log message?
Hope someone can help me
Regards
Markus
StackTrace1:
javax.servlet.ServletException: SelectOne submittedValue''s index 3 is out of
bounds. It should be between 0 and 0
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:154)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._invokeDoFilter(TrinidadFilterImpl.java:262)
at
org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:219)
at
org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:173)
at
org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
de.tccproducts.dps.web.utils.lifecycle.ExceptionFilter.doFilter(ExceptionFilter.java:35)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at
org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
at
org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at
org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.IndexOutOfBoundsException: SelectOne submittedValue''s
index 3 is out of bounds. It should be between 0 and 0
at
org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SimpleSelectOneRenderer.__getIndex(SimpleSelectOneRenderer.java:414)
at
org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SimpleSelectOneRenderer._convertIndexedSubmittedValue(SimpleSelectOneRenderer.java:214)
at
org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SimpleSelectOneRenderer.getConvertedValue(SimpleSelectOneRenderer.java:181)
at
org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.InputLabelAndMessageRenderer.getConvertedValue(InputLabelAndMessageRenderer.java:65)
at
org.apache.myfaces.trinidad.component.UIXEditableValue.getConvertedValue(UIXEditableValue.java:421)
at
org.apache.myfaces.trinidad.component.UIXEditableValue.validate(UIXEditableValue.java:163)
at
org.apache.myfaces.trinidad.component.UIXEditableValue._executeValidate(UIXEditableValue.java:488)
at
org.apache.myfaces.trinidad.component.UIXEditableValue.processValidators(UIXEditableValue.java:269)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildrenImpl(UIXComponentBase.java:939)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildren(UIXComponentBase.java:923)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.processValidators(UIXComponentBase.java:758)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildrenImpl(UIXComponentBase.java:939)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildren(UIXComponentBase.java:923)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.processValidators(UIXComponentBase.java:758)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildrenImpl(UIXComponentBase.java:939)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildren(UIXComponentBase.java:923)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.processValidators(UIXComponentBase.java:758)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildrenImpl(UIXComponentBase.java:939)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildren(UIXComponentBase.java:923)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.processValidators(UIXComponentBase.java:758)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildrenImpl(UIXComponentBase.java:939)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildren(UIXComponentBase.java:923)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.processValidators(UIXComponentBase.java:758)
at
org.apache.myfaces.trinidad.component.UIXSubform.processValidators(UIXSubform.java:143)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildrenImpl(UIXComponentBase.java:939)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildren(UIXComponentBase.java:923)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.processValidators(UIXComponentBase.java:758)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildrenImpl(UIXComponentBase.java:939)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildren(UIXComponentBase.java:923)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.processValidators(UIXComponentBase.java:758)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildrenImpl(UIXComponentBase.java:939)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildren(UIXComponentBase.java:923)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.processValidators(UIXComponentBase.java:758)
at
org.apache.myfaces.trinidad.component.UIXForm.processValidators(UIXForm.java:82)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildrenImpl(UIXComponentBase.java:939)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.validateChildren(UIXComponentBase.java:923)
at
org.apache.myfaces.trinidad.component.UIXComponentBase.processValidators(UIXComponentBase.java:758)
at
javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:149)
at
org.apache.myfaces.lifecycle.ProcessValidationsExecutor.execute(ProcessValidationsExecutor.java:32)
at
org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:95)
at
org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:70)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:139)
... 27 more
EnumConverterSource:
package de.tccproducts.dps.web.utils.converter;
import javax.faces.component.*;
import javax.faces.context.*;
import javax.faces.convert.*;
import org.apache.commons.lang.*;
public class EnumConverter implements Converter {
private Class<? extends Enum> type;
public Class<? extends Enum> getType() {
return type;
}
public void setType(Class<? extends Enum> type) {
this.type = type;
}
@SuppressWarnings("unchecked")
public Object getAsObject(FacesContext context, UIComponent
component, String paramString) throws ConverterException {
if(StringUtils.isBlank(paramString)) {
return null;
}
return Enum.valueOf(type, paramString);
}
public String getAsString(FacesContext context, UIComponent
component, Object paramObject) throws ConverterException {
if(paramObject == null) {
return "";
}
return paramObject.toString();
}
}