[
https://issues.apache.org/jira/browse/MYFACES-1452?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12471087
]
Paul Iov commented on MYFACES-1452:
-----------------------------------
Hi All.
I have the same issue with selectBooleanCheckbox SNAPSHOT-1.1.5 I'm not sure
whether this behaviour violates the JSF specification directly. Any way, the
description of value attribute from TLD says:
-----
The initial value of this component. This value is generally
set as a value-binding in the form #{myBean.myProperty}, where
myProperty can be any data-type of Java (also user-defined data-types),
if a converter for this data-type exists.
---
I've checked the source code and found, that the root of problem is the
implementation of getBooleanValue() in
org.apache.myfaces.shared.renderkit.RendererUtils class, which is called from
encodeEnd() of renderer.
The custom converter as well as default one is cosequently ignored and
IllegalArgumentException is thrown, if component value is neither of type
Boolean nor null. (h:selectBooleanCheckbox and t:selectBooleanCheckbox are
affected!)
It was difficult for me to check all dependencies of this function. I'm not
sure, whether it is called by any other renderer with more 'strictly'
behaviour. Keeping this in mind I decide to provide the new one, named
getBooleanValueForCheckbox(). If I'm right and if my solution is correct, this
function cann be renamed into getBooleanValue() and current one cann be
replaced/overloaded with it, because my version hase 2 parameters. (Generally
it's not a good idea to overload such methods.)
By the way: the same problem is solved in HtmlCalendar (which was a start point
of my 'research' since my custom converter works with this component pretty
well) directly in renderer, but I believe that it's not right to do this at
'high' level, living unused methods at 'low' level.
Unfortunatelly I wasn't able to build wohl project due to time constraints. So
I provide no path but post my source code right here and hope, that somebody
cann review this and check in to the next nightly build.
SY,
paul
org.apache.myfaces.shared.renderkit.RendererUtils
<code>
public static Boolean getBooleanValueForCheckbox(FacesContext facesContext,
UIComponent component) {
Object value = getObjectValue(component);
//This call relays on the implementation of getObjectValue()!!!
//If uiComponent is not an instance of ValueHolder, the
//IllegalArgumentException should be already thrown.
Converter converter = ((ValueHolder)uiComponent).getConverter();
if (null == value || value instanceof Boolean){
return (Boolean)value;
}
if (null == converter && value instanceof String) {
//it's still correct to convert String into Boolean, because
Boolean provides constructor Boolean(String x)!
return new Boolean(value);
}
//If component provides no custom converter, we
//must try to obtain a standard one from Application!
if( null == converter ){
try {
converter =
facesContext.getApplication().createConverter(value.getClass());
}
catch (FacesException ex) {
throw new IllegalArgumentException("Component : " +
getPathToComponent(component)+
" expects value of type Boolean.\n"+
"Neither standard converter for " +
value.getClass().getName() +
" nor custom converter provided." );
}
}
if (null != converter){
try{
//Try to convert it into String. That is! The getAsObject()
provides
//the convertion of string value's representation into
custom user type.
//We are expecting a Boolean, but the value itself is not a
Boolean, so
//we need to get String first.
String strValue = converter.getAsString(facesContext,
component, value);
boolean warn = (null == strValue);
warn = warn || (!
strValue.equalsIgnoreCase(Boolean.TRUE.toString() &&
!
strValue.equalsIgnoreCase(Boolean.TRUE.toString() );
if ( wran ){
//Note that this situation is not an error! We have
some converter
//and it got back some string, and no exception hase
been thrown!
log.warn("Component " + getPathToComponent(component) +
" expects value of type Boolean. The
value was converted with "+
converter.getClass().getName()+
" into " + strValue+ ", what is
neither true nor false! false assumed.");
}
return new Boolean(strValue);
}
catch (ConverterException ex){
throw new IllegalArgumentException("Component : " +
getPathToComponent(component)+
" expects value of type
Boolean.\n"+
"Unable to convert " +
value.getClass().getName() +
" into Boolean.");
}
} else {
throw new IllegalArgumentException("Component " +
getPathToComponent(component)+
" expects value of type Boolean but " +
value.getClass().getName() + " was found.");
}
}
</code>
/*
change:
org.apache.myfaces.shared.renderkit.html.HtmlCheckboxRendererBase
*/
<code>
public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
throws IOException {
org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext,
uiComponent, null);
if (uiComponent instanceof UISelectBoolean) {
Boolean value =
org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanValue( uiComponent
);
boolean isChecked = value != null ? value.booleanValue() :
false;
renderCheckbox(facesContext, uiComponent, EXTERNAL_TRUE_VALUE,
null, false,isChecked, true);
} else if (uiComponent instanceof UISelectMany) {
renderCheckboxList(facesContext, (UISelectMany) uiComponent);
} else {
throw new IllegalArgumentException("Unsupported component class "
+ uiComponent.getClass().getName());
}
}
/*
into:
*/
public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
throws IOException {
org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(
facesContext, uiComponent, null);
if (uiComponent instanceof UISelectBoolean) {
// Boolean value =
//
org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanValue(
// uiComponent );
Boolean value =
org.apache.myfaces.shared.renderkit.RendererUtils
.getBooleanValueForCheckbox(facesContext, uiComponent);
// boolean isChecked = value != null ?
value.booleanValue() : false;
boolean isChecked = value.booleanValue();
renderCheckbox(facesContext, uiComponent,
EXTERNAL_TRUE_VALUE,
null, false, isChecked, true);
} else if (uiComponent instanceof UISelectMany) {
renderCheckboxList(facesContext, (UISelectMany)
uiComponent);
} else {
throw new IllegalArgumentException("Unsupported
component class "
+ uiComponent.getClass().getName());
}
}
</code>
> selectBooleanCheckBox: Expected submitted value of type Boolean for Component
> -----------------------------------------------------------------------------
>
> Key: MYFACES-1452
> URL: https://issues.apache.org/jira/browse/MYFACES-1452
> Project: MyFaces Core
> Issue Type: Bug
> Components: JSR-127
> Affects Versions: 1.1.1, 1.1.4
> Environment: Windows XP Professional SP 1; Tomcat 5.0.27
> Reporter: Holger Niehaus
>
> I use following code in JSF:
> <h:selectBooleanCheckbox value="#{conf.zero}"
> converter="NumberBooleanConverter" />
> conf.zero returns an Integer ( 0 or 1). Converter returns "true" or "false"
> (String), but getAsString isn`t called. Instead the exception is thrown (see
> below). Same effect with extension (x:selectBooleanCheckbox). For inputText
> (<h:inputText value="#{conf.one}" converter="NumberBooleanConverter" />) it
> works. Is it a similar reason as in Bug ADFFACES-38? Or am I on the wrong
> track?
> Thrown exception:
> javax.faces.FacesException: Expected submitted value of type Boolean for
> Component : {Component-Path : [Class:
> javax.faces.component.UIViewRoot,ViewId:
> /jsp/common/rechte/matrix_behoerde.jsp][Class:
> javax.faces.component.html.HtmlForm,Id: behoerde_matrix][Class:
> javax.faces.component.html.HtmlPanelGroup,Id: _id0][Class:
> org.apache.myfaces.component.html.ext.HtmlDataTable,Id: matrix][Class:
> javax.faces.component.UIColumn,Id: _id33][Class:
> org.apache.myfaces.component.html.ext.HtmlSelectBooleanCheckbox,Id: _id35]}
>
> org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:421)
>
> org.apache.myfaces.application.jsp.JspViewHandlerImpl.renderView(JspViewHandlerImpl.java:234)
>
> org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:352)
> javax.faces.webapp.FacesServlet.service(FacesServlet.java:107)
>
> org.apache.myfaces.component.html.util.ExtensionsFilter.doFilter(ExtensionsFilter.java:92)
>
> org.apache.myfaces.component.html.util.ExtensionsFilter.doFilter(ExtensionsFilter.java:122)
> de.filter.AccessFilter.doFilter(AccessFilter.java:93)
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.