MyFaces Core
  1. MyFaces Core
  2. MYFACES-2873

Provide a way to change the order of ELResolvers

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.2.9, 2.0.1
    • Fix Version/s: 1.2.11, 2.0.8, 2.1.2
    • Component/s: None
    • Labels:
      None

      Description

      When using CDI or Spring or any other framework/lib that provides a custom ELResolver there can be performance problems, because the custom ELResolvers from the faces-config are plugged in pretty early in the resolver chain.

      For CDI this means that for lots of trivial ELExpressions (like Array or Map value lookups) the CDI-ELResolver gets called and this resolver is not very performant, because it has to go through all Objects which are handled by CDI to find the fitting one. And in the most cases it won't find a fitting object, because the requested value is not handled by CDI.

      JSF currently only allows to sort the ELResolvers from different faces-config files, but not to change the order of predefined ELResolvers (like e.g. MapELResolver). Thus talking with Mark Struberg and Gerhard Petracek we came up with a Comparator<ELResolver> solution for this problem.

      The user can define a Comparator<ELResolver> via a web.xml config param and this comparator will be used to sort the ELResolvers before they are applied (but of course, only once). In addition we provide 3 default implementations: one to put every ELResolver from the faces-config to the front, one to put them to the back and one optimized for OpenWebBeans.

      This solution gives you many improvements:

      • you can tune your application by a customized order of ELResolvers
      • you don't need MyFaces implementation classes, but only a simple Comparator
      • if you switch to Mojarra or a earlier version of MyFaces, the ordering just won't work, but the behavior of the ELResolvers is the same

      The context-parameter will look like this (for the OWB-optimized resolver):

      <context-param>
      <param-name>org.apache.myfaces.EL_RESOLVER_COMPARATOR</param-name>
      <param-value>org.apache.myfaces.el.unified.OpenWebBeansELResolverComparator</param-value>
      </context-param>

      1. MYFACES-2873.patch
        27 kB
        Jakob Korherr

        Activity

        Hide
        Jakob Korherr added a comment -

        The patch includes the support for setting a Comparator<ELResolver> via the org.apache.myfaces.EL_RESOLVER_COMPARATOR context-parameter and it also includes 3 default implementations:

        • org.apache.myfaces.el.unified.OpenWebBeansELResolverComparator
        • org.apache.myfaces.el.unified.CustomFirstELResolverComparator
        • org.apache.myfaces.el.unified.CustomLastELResolverComparator

        If there are no objections, I will commit this patch soon.

        Show
        Jakob Korherr added a comment - The patch includes the support for setting a Comparator<ELResolver> via the org.apache.myfaces.EL_RESOLVER_COMPARATOR context-parameter and it also includes 3 default implementations: org.apache.myfaces.el.unified.OpenWebBeansELResolverComparator org.apache.myfaces.el.unified.CustomFirstELResolverComparator org.apache.myfaces.el.unified.CustomLastELResolverComparator If there are no objections, I will commit this patch soon.
        Hide
        Jakob Korherr added a comment -

        Documentation about this new feature in the cwiki: https://cwiki.apache.org/confluence/display/MYFACES/ELResolver+ordering

        Show
        Jakob Korherr added a comment - Documentation about this new feature in the cwiki: https://cwiki.apache.org/confluence/display/MYFACES/ELResolver+ordering
        Hide
        Bernd Bohmann added a comment -

        Should this feature myfaces 2.0 only? What about 1.2?

        Show
        Bernd Bohmann added a comment - Should this feature myfaces 2.0 only? What about 1.2?
        Hide
        Jakob Korherr added a comment -

        You are right, Bernd. We can do this for 1.2.x too!

        Show
        Jakob Korherr added a comment - You are right, Bernd. We can do this for 1.2.x too!
        Hide
        Jakob Korherr added a comment -

        Now it works in 2.0.2 and 1.2.10.

        Show
        Jakob Korherr added a comment - Now it works in 2.0.2 and 1.2.10.
        Hide
        Leonardo Uribe added a comment -

        Reported on users list this exception (using 1.2.10)

        After changing the MyFaces Core Jar's from version 1.2.9 to version 1.2.10,
        I am getting the following NullPointerException:

        INFO: Server startup in 1352 ms
        Mar 2, 2011 8:57:08 AM org.apache.catalina.core.StandardWrapperValve invoke
        SEVERE: Servlet.service() for servlet Faces Servlet threw exception
        java.lang.NullPointerException
        at org.apache.myfaces.el.unified.ResolverBuilderBase.sortELResolvers(
        ResolverBuilderBase.java:114)
        at org.apache.myfaces.el.unified.ResolverBuilderForFaces.build(
        ResolverBuilderForFaces.java:63)
        at org.apache.myfaces.application.ApplicationImpl.createFacesResolver
        (ApplicationImpl.java:189)
        at org.apache.myfaces.application.ApplicationImpl.getELResolver(
        ApplicationImpl.java:181)
        at org.apache.myfaces.trinidadinternal.config.LazyValueExpression
        $MockELContext.<init>(LazyValueExpression.java:194)
        at
        org.apache.myfaces.trinidadinternal.config.LazyValueExpression._getELContext
        (
        LazyValueExpression.java:143)
        at
        org.apache.myfaces.trinidadinternal.config.LazyValueExpression._createValueExpressionFromApplication
        (
        LazyValueExpression.java:176)
        at
        org.apache.myfaces.trinidadinternal.config.LazyValueExpression.createValueExpression
        (
        LazyValueExpression.java:55)
        at org.apache.myfaces.trinidadinternal.config.ConfigParser
        $Handler.endElement(ConfigParser.java:252)
        at
        com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(
        AbstractSAXParser.java:601)
        at
        com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement
        (
        XMLDocumentFragmentScannerImpl.java:1782)
        at
        com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl
        $FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2938)
        at
        com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(
        XMLDocumentScannerImpl.java:648)
        at
        com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(
        XMLNSDocumentScannerImpl.java:140)
        at
        com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument
        (
        XMLDocumentFragmentScannerImpl.java:511)
        at
        com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(
        XML11Configuration.java:808)
        at
        com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(
        XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(
        XMLParser.java:119)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse
        (AbstractSAXParser.java:1205)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl
        $JAXPSAXParser.parse(SAXParserImpl.java:522)
        at
        org.apache.myfaces.trinidadinternal.config.ConfigParser.parseConfigFile(
        ConfigParser.java:81)
        at
        org.apache.myfaces.trinidadinternal.context.RequestContextFactoryImpl._getBean
        (
        RequestContextFactoryImpl.java:71)
        at
        org.apache.myfaces.trinidadinternal.context.RequestContextFactoryImpl.createContext
        (
        RequestContextFactoryImpl.java:56)
        at
        org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl._attachRequestContext
        (
        GlobalConfiguratorImpl.java:470)
        at
        org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl.beginRequest
        (
        GlobalConfiguratorImpl.java:208)
        at
        org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(
        TrinidadFilterImpl.java:155)
        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 org.apache.catalina.core.StandardWrapperValve.invoke(
        StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(
        StandardContextValve.java:191)
        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:293)
        at org.apache.coyote.http11.Http11Processor.process(
        Http11Processor.java:849)
        at org.apache.coyote.http11.Http11Protocol
        $Http11ConnectionHandler.process(Http11Protocol.java:583)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(
        JIoEndpoint.java:454)
        at java.lang.Thread.run(Thread.java:662)
        FormularDBNew: 2011-03-02 08:57:08,800 ERROR [http-8080-1]
        javax.faces.webapp._ErrorPageWriter: An exception occurred
        java.lang.NullPointerException
        at
        org.apache.myfaces.trinidadinternal.renderkit.RenderKitDecorator.getRenderKit
        (
        RenderKitDecorator.java:119)
        at
        org.apache.myfaces.trinidadinternal.renderkit.RenderKitDecorator.getResponseStateManager
        (
        RenderKitDecorator.java:70)
        at
        org.apache.myfaces.shared_impl.renderkit.RendererUtils.getResponseStateManager
        (
        RendererUtils.java:1184)
        at org.apache.myfaces.lifecycle.DefaultRestoreViewSupport.isPostback(
        DefaultRestoreViewSupport.java:141)
        at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute(
        RestoreViewExecutor.java:80)
        at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(
        LifecycleImpl.java:103)
        at org.apache.myfaces.lifecycle.LifecycleImpl.execute(
        LifecycleImpl.java:76)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:183)
        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.ApplicationDispatcher.invoke(
        ApplicationDispatcher.java:646)
        at org.apache.catalina.core.ApplicationDispatcher.processRequest(
        ApplicationDispatcher.java:438)
        at org.apache.catalina.core.ApplicationDispatcher.doForward(
        ApplicationDispatcher.java:374)
        at org.apache.catalina.core.ApplicationDispatcher.forward(
        ApplicationDispatcher.java:302)
        at org.apache.catalina.core.StandardHostValve.custom(
        StandardHostValve.java:416)
        at org.apache.catalina.core.StandardHostValve.throwable(
        StandardHostValve.java:271)
        at org.apache.catalina.core.StandardHostValve.invoke(
        StandardHostValve.java:142)
        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:293)
        at org.apache.coyote.http11.Http11Processor.process(
        Http11Processor.java:849)
        at org.apache.coyote.http11.Http11Protocol
        $Http11ConnectionHandler.process(Http11Protocol.java:583)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(
        JIoEndpoint.java:454)
        at java.lang.Thread.run(Thread.java:662)

        Show
        Leonardo Uribe added a comment - Reported on users list this exception (using 1.2.10) After changing the MyFaces Core Jar's from version 1.2.9 to version 1.2.10, I am getting the following NullPointerException: INFO: Server startup in 1352 ms Mar 2, 2011 8:57:08 AM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet Faces Servlet threw exception java.lang.NullPointerException at org.apache.myfaces.el.unified.ResolverBuilderBase.sortELResolvers( ResolverBuilderBase.java:114) at org.apache.myfaces.el.unified.ResolverBuilderForFaces.build( ResolverBuilderForFaces.java:63) at org.apache.myfaces.application.ApplicationImpl.createFacesResolver (ApplicationImpl.java:189) at org.apache.myfaces.application.ApplicationImpl.getELResolver( ApplicationImpl.java:181) at org.apache.myfaces.trinidadinternal.config.LazyValueExpression $MockELContext.<init>(LazyValueExpression.java:194) at org.apache.myfaces.trinidadinternal.config.LazyValueExpression._getELContext ( LazyValueExpression.java:143) at org.apache.myfaces.trinidadinternal.config.LazyValueExpression._createValueExpressionFromApplication ( LazyValueExpression.java:176) at org.apache.myfaces.trinidadinternal.config.LazyValueExpression.createValueExpression ( LazyValueExpression.java:55) at org.apache.myfaces.trinidadinternal.config.ConfigParser $Handler.endElement(ConfigParser.java:252) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement( AbstractSAXParser.java:601) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement ( XMLDocumentFragmentScannerImpl.java:1782) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2938) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next( XMLDocumentScannerImpl.java:648) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next( XMLNSDocumentScannerImpl.java:140) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument ( XMLDocumentFragmentScannerImpl.java:511) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse( XML11Configuration.java:808) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse( XML11Configuration.java:737) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse( XMLParser.java:119) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse (AbstractSAXParser.java:1205) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $JAXPSAXParser.parse(SAXParserImpl.java:522) at org.apache.myfaces.trinidadinternal.config.ConfigParser.parseConfigFile( ConfigParser.java:81) at org.apache.myfaces.trinidadinternal.context.RequestContextFactoryImpl._getBean ( RequestContextFactoryImpl.java:71) at org.apache.myfaces.trinidadinternal.context.RequestContextFactoryImpl.createContext ( RequestContextFactoryImpl.java:56) at org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl._attachRequestContext ( GlobalConfiguratorImpl.java:470) at org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl.beginRequest ( GlobalConfiguratorImpl.java:208) at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter( TrinidadFilterImpl.java:155) 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 org.apache.catalina.core.StandardWrapperValve.invoke( StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke( StandardContextValve.java:191) 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:293) at org.apache.coyote.http11.Http11Processor.process( Http11Processor.java:849) at org.apache.coyote.http11.Http11Protocol $Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run( JIoEndpoint.java:454) at java.lang.Thread.run(Thread.java:662) FormularDBNew: 2011-03-02 08:57:08,800 ERROR [http-8080-1] javax.faces.webapp._ErrorPageWriter: An exception occurred java.lang.NullPointerException at org.apache.myfaces.trinidadinternal.renderkit.RenderKitDecorator.getRenderKit ( RenderKitDecorator.java:119) at org.apache.myfaces.trinidadinternal.renderkit.RenderKitDecorator.getResponseStateManager ( RenderKitDecorator.java:70) at org.apache.myfaces.shared_impl.renderkit.RendererUtils.getResponseStateManager ( RendererUtils.java:1184) at org.apache.myfaces.lifecycle.DefaultRestoreViewSupport.isPostback( DefaultRestoreViewSupport.java:141) at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute( RestoreViewExecutor.java:80) at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase( LifecycleImpl.java:103) at org.apache.myfaces.lifecycle.LifecycleImpl.execute( LifecycleImpl.java:76) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:183) 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.ApplicationDispatcher.invoke( ApplicationDispatcher.java:646) at org.apache.catalina.core.ApplicationDispatcher.processRequest( ApplicationDispatcher.java:438) at org.apache.catalina.core.ApplicationDispatcher.doForward( ApplicationDispatcher.java:374) at org.apache.catalina.core.ApplicationDispatcher.forward( ApplicationDispatcher.java:302) at org.apache.catalina.core.StandardHostValve.custom( StandardHostValve.java:416) at org.apache.catalina.core.StandardHostValve.throwable( StandardHostValve.java:271) at org.apache.catalina.core.StandardHostValve.invoke( StandardHostValve.java:142) 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:293) at org.apache.coyote.http11.Http11Processor.process( Http11Processor.java:849) at org.apache.coyote.http11.Http11Protocol $Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run( JIoEndpoint.java:454) at java.lang.Thread.run(Thread.java:662)
        Hide
        Leonardo Uribe added a comment -

        I reviewed the stack trace and the problem is an EL expressions is created from a location where no ExternalContext is setup (TrinidadFilter).

        The comparator or predicate used to sort/filter EL resolvers should be created by FacesConfigurator and attached to RuntimeConfig object, so it just can be used from Application implementation instance later without retrieve ExternalContext instance. I thought it was something related to the algorithm but at the end it was a side effect. Thanks for the report.

        Show
        Leonardo Uribe added a comment - I reviewed the stack trace and the problem is an EL expressions is created from a location where no ExternalContext is setup (TrinidadFilter). The comparator or predicate used to sort/filter EL resolvers should be created by FacesConfigurator and attached to RuntimeConfig object, so it just can be used from Application implementation instance later without retrieve ExternalContext instance. I thought it was something related to the algorithm but at the end it was a side effect. Thanks for the report.
        Hide
        Jakob Korherr added a comment -

        good solution. Thanks, Leo!

        Show
        Jakob Korherr added a comment - good solution. Thanks, Leo!

          People

          • Assignee:
            Leonardo Uribe
            Reporter:
            Jakob Korherr
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development