myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Leonardo Uribe (Commented) (JIRA)" <...@myfaces.apache.org>
Subject [jira] [Commented] (MYFACES-3304) NullPointerException using h:selectOneRadio with an enum
Date Thu, 06 Oct 2011 15:35:29 GMT

    [ https://issues.apache.org/jira/browse/MYFACES-3304?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13122008#comment-13122008
] 

Leonardo Uribe commented on MYFACES-3304:
-----------------------------------------

The following notations work:

  <f:selectItem itemValue="#{'VALUEA'}" itemLabel="labelA"/>
  <f:selectItem itemValue="#{'VALUEB'}" itemLabel="labelB"/> 

  <f:selectItem itemValue="VALUEA" itemLabel="labelA"/>
  <f:selectItem itemValue="VALUEB" itemLabel="labelB"/> 


    public TestEnum getValueA()
    {
        return TestEnum.VALUEA;
    }

    public TestEnum getValueB()
    {
        return TestEnum.VALUEB;
    }

  <f:selectItem itemValue="#{testLovsBean.valueA}" itemLabel="labelA"/>
  <f:selectItem itemValue="#{testLovsBean.valueB}" itemLabel="labelB"/>

So if #{VALUEA} and #{VALUEB} resolve to the expected enum value it should work. The syntax
used here is just invalid. 

But the example shows another problem. I tried the same example with mojarra and the page
is rendered and the null option is a valid choice, but as soon as you select it on the next
request the selected radio button is unselected. If you have a selectOne component attached
to an enum, it is valid to add a null option (but in practice if you are using an enum you
usually use another option on the enum). In that case, EnumConverter will fail to convert
that null value into a valid enum value anyway but you still can provide a custom converter
that check the null value and deal with it.

The other problem with this component is if you don't set value="", when the form is submitted
the value "on" will be passed (tried on firefox), so set itemStrValue to "" is reasonable,
but at the end this is resposibility of the code that renders at the end the component. The
reason why in mojarra that option is unselected as soon as is selected and submited is ""
!= null, so when "" is received, it is not associated to the null option.

In conclusion, we should "at least" behave the same as Mojarra in this case. But I still have
my doubts about that. For example, someone can say we should honor javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL
web config param in this case. It that param is set to true, as soon as a "" is received,
it is converted to null, and since there is a null option, this option should be selected.
But if this is false, for this specific component an empty "" is ALWAYS the same as a null
value.

I think we should fix some parts of the code to reflect that. First of all check for null
before render an option value and render "" in that case. Second take into account that for
this specific case  an empty "" is ALWAYS the same as a null value. And finally don't return
"" when a String value for the renderer is calculated and return null, just for keep things
clear. I'll attach a patch for this one, but first we need to check if the change does not
make the TCK fails before commit.

                
> NullPointerException using h:selectOneRadio with an enum
> --------------------------------------------------------
>
>                 Key: MYFACES-3304
>                 URL: https://issues.apache.org/jira/browse/MYFACES-3304
>             Project: MyFaces Core
>          Issue Type: Bug
>    Affects Versions: 2.0.8
>         Environment: Ubuntu 11.0.4, Jetty 6.1.10, JDK 1.6, Myfaces Core 2.0.8, Primefaces
3.0.M3
>            Reporter: Joe Rossi
>            Priority: Minor
>
> Trying to use a h:selectOneRadio to select one of two values for an enum and it fails,
throwing a NullPointerException. No explicit converter is in use so (from debugging) it appears
to be using the default EnumConverter.
> Code snippets in question are as follows:
> testLovs.xhtml:
>     <h:panelGrid columns="1">
>       Simple radio button with constant string values
>       <h:selectOneRadio id="l1" value="#{testLovsBean.l1}">
>          <f:selectItem itemValue="A" itemLabel="labelA"/>
>          <f:selectItem itemValue="B" itemLabel="labelB"/>
>       </h:selectOneRadio>
>       <h:outputText id="l1Str" value="l1: #{testLovBean.l1AsString}"/>
>       <p:separator/>
>       Radio button for enum
>       <h:selectOneRadio id="l2" value="#{testLovsBean.l2}">
>          <f:selectItem itemValue="#{VALUEA}" itemLabel="labelA"/>
>          <f:selectItem itemValue="#{VALUEB}" itemLabel="labelB"/>
>       </h:selectOneRadio>
>       <h:outputText id="l2Str" value="l2: #{testLovBean.l2AsString}"/>
>       <p:separator/>
>       <p:commandButton id="commitCommand"
>         action="#{testLovsBean.commitAction}"
>         value="Submit"
>         ajax="false"/>
> TestLovsBean.java:
> package tn.view.bean.test;
> import org.springframework.context.annotation.Scope;
> import org.springframework.stereotype.Component;
> import tn.view.util.FacesUtils;
> /**
>  * Class used for testing date controls
>  */
> @Component
> @Scope("request")
> public class TestLovsBean
> {
>   public TestLovsBean()
>   {
>   }
>   public String getL1()
>   {
>     return _l1;
>   }
>   public void setL1(String l1)
>   {
>     _l1 = l1;
>   }
>   public String getL1AsString()
>   {
>     return _l1;
>   }
>   public TestEnum getL2()
>   {
>     return _l2;
>   }
>   public void setL2(TestEnum l2)
>   {
>     _l2 = l2;
>   }
>   public String commitAction()
>   {
>     System.out.println("commitAction invoked");
>     FacesUtils.addInfoMessage("L1: " + _l1);
>     FacesUtils.addInfoMessage("L2: " + _l2);
>     return null;
>   }
>   private String _l1;
>   private TestEnum _l2;
> }
> TestEnum.java:
> package tn.view.bean.test;
> public enum TestEnum
> {
>   VALUEA,
>   VALUEB,
> }
> Stack trace:
> javax.servlet.ServletException
> 	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:221)
> 	at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
> 	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093)
> 	at tn.view.error.ResponseCapturingFilter.doFilter(ResponseCapturingFilter.java:83)
> 	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
> 	at tn.view.error.AbstractUncaughtExceptionInterceptor.doFilter(AbstractUncaughtExceptionInterceptor.java:66)
> 	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
> 	at net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:292)
> 	at net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:108)
> 	at net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter.doFilter(SecurityEnforcementFilter.java:197)
> 	at net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
> 	at net.sf.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:143)
> 	at net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
> 	at net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter.doFilter(BasicProcessingFilter.java:214)
> 	at net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
> 	at net.sf.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:324)
> 	at net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
> 	at net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:220)
> 	at net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
> 	at net.sf.acegisecurity.securechannel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:168)
> 	at tn.security.CustomChannelProcessingFilter.doFilter(CustomChannelProcessingFilter.java:23)
> 	at net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
> 	at net.sf.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:173)
> 	at net.sf.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:120)
> 	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
> 	at net.sf.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:50)
> 	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
> 	at tn.view.filter.StaticContentCachingFilter.doFilter(StaticContentCachingFilter.java:85)
> 	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
> 	at tn.view.error.AbstractUncaughtExceptionFilter.doFilter(AbstractUncaughtExceptionFilter.java:81)
> 	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
> 	at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
> 	at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
> 	at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
> 	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
> 	at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
> 	at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)
> 	at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
> 	at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:211)
> 	at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
> 	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
> 	at org.mortbay.jetty.Server.handle(Server.java:313)
> 	at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:506)
> 	at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:830)
> 	at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:514)
> 	at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
> 	at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)
> 	at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:227)
> 	at org.mortbay.jetty.security.SslSocketConnector$SslConnection.run(SslSocketConnector.java:626)
> 	at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:442)
> Caused by: java.lang.NullPointerException
> 	at org.apache.myfaces.shared.renderkit.html.HtmlRadioRendererBase.renderGroupOrItemRadio(HtmlRadioRendererBase.java:221)
> 	at org.apache.myfaces.shared.renderkit.html.HtmlRadioRendererBase.encodeEnd(HtmlRadioRendererBase.java:126)
> 	at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:539)
> 	at org.apache.myfaces.shared.renderkit.RendererUtils.renderChild(RendererUtils.java:551)
> 	at org.apache.myfaces.shared.renderkit.html.HtmlGridRendererBase.renderChildren(HtmlGridRendererBase.java:334)
> 	at org.apache.myfaces.shared.renderkit.html.HtmlGridRendererBase.encodeEnd(HtmlGridRendererBase.java:169)
> 	at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:539)
> 	at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:64)
> 	at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:48)
> 	at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:62)
> 	at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:48)
> 	at org.primefaces.component.layout.LayoutUnitRenderer.encodeEnd(LayoutUnitRenderer.java:51)
> 	at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:539)
> 	at javax.faces.component.UIComponent.encodeAll(UIComponent.java:641)
> 	at javax.faces.component.UIComponent.encodeAll(UIComponent.java:637)
> 	at javax.faces.component.UIComponent.encodeAll(UIComponent.java:637)
> 	at javax.faces.component.UIComponent.encodeAll(UIComponent.java:637)
> 	at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1481)
> 	at org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:264)
> 	at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:90)
> 	at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:239)
> 	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:191)
> 	... 49 more

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Mime
View raw message