Hi

Thanks for the demo, it helps a lot. I tried th with myfaces and it throws
the same exception:

javax.faces.FacesException: java.lang.NullPointerException: name can not be null
        at 
org.apache.myfaces.shared_impl.context.ExceptionHandlerImpl.wrap(ExceptionHandlerImpl.java:241)

        at 
org.apache.myfaces.shared_impl.context.ExceptionHandlerImpl.handle(ExceptionHandlerImpl.java:156)
        at 
org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:169)
        at 
org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:96)

        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
        at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

        at 
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at 
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
        at 
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)

        at 
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at 
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at 
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)

        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:447)

        at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.NullPointerException: name can not be null
        at 
javax.faces.component.UIComponent.getValueExpression(UIComponent.java:543)
        at 
org.apache.myfaces.el.unified.resolver.CompositeComponentELResolver$CompositeComponentAttributesMapWrapper.getExpression(CompositeComponentELResolver.java:208)

        at 
org.apache.myfaces.extensions.validator.core.el.ExtValELResolver.getCompositeComponentExpression(ExtValELResolver.java:277)
        at 
org.apache.myfaces.extensions.validator.core.el.DefaultELHelper.getPropertyDetailsOfValueBinding(DefaultELHelper.java:169)

        at 
org.apache.myfaces.extensions.validator.core.metadata.extractor.DefaultComponentMetaDataExtractor.extract(DefaultComponentMetaDataExtractor.java:77)
        at 
org.apache.myfaces.extensions.validator.util.ExtValUtils$1.extract(ExtValUtils.java:233)

        at 
org.apache.myfaces.extensions.validator.core.interceptor.AbstractValidationInterceptor.getPropertyInformation(AbstractValidationInterceptor.java:176)
        at 
org.apache.myfaces.extensions.validator.core.interceptor.AbstractValidationInterceptor.processAfterValidation(AbstractValidationInterceptor.java:166)

        at 
org.apache.myfaces.extensions.validator.core.interceptor.AbstractValidationInterceptor.beforeGetConvertedValue(AbstractValidationInterceptor.java:153)
        at 
org.apache.myfaces.extensions.validator.core.renderkit.ExtValRendererWrapper.getConvertedValue(ExtValRendererWrapper.java:369)

        at javax.faces.component.UIInput.getConvertedValue(UIInput.java:578)
        at javax.faces.component.UIInput.validate(UIInput.java:510)
        at javax.faces.component.UIInput.processValidators(UIInput.java:240)
        at 
javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1218)

        at 
javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1218)
        at javax.faces.component.UIForm.processValidators(UIForm.java:137)
        at 
javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1218)

        at 
javax.faces.component.UIViewRoot._processValidatorsDefault(UIViewRoot.java:1251)
        at javax.faces.component.UIViewRoot.access$500(UIViewRoot.java:77)
        at 
javax.faces.component.UIViewRoot$ProcessValidatorPhaseProcessor.process(UIViewRoot.java:1298)

        at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1207)
        at 
javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:683)
        at 
org.apache.myfaces.lifecycle.ProcessValidationsExecutor.execute(ProcessValidationsExecutor.java:34)

        at 
org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:149)

The problem resides in how CompositeComponentELResolver works. In few words,
it returns a Map that points to composite component attributes, but this map
is traversed by default MapELResolver, not the same
CompositeComponentELResolver, so ExtValELResolver wrapper does not receive
the control before evaluate and compositeComponentExpressionBase is never
set.

The solution should be do something similar to the hack done in
FlashELResolver. In that case, the resolver checks if the base is instanceof
the map (in myfaces case CompositeComponentAttributesMapWrapper) and if so
return the value as MapELResolver does (or in other words as FlashELResolver
does).

I have not tested this solution yet but I think it will work. The behavior
proposed is not described on jsf 2.0 spec section 5.6.2.2, but I think we
can consider it an implementation detail and create a fix on myfaces. Please
create an issue on myfaces issue tracker and I'll propose a patch for this
one.

regards,

Leonardo Uribe

Reply via email to