My EL Expressions are not being evaluated under a

2020-03-31 06:02发布

问题:

I have a MyFaces application running under Spring Boot 2.0.3, all Servlets and Context Listeners are properly registered and configured, and apparently working. Even my index.jsf page is being rendered. The tags are processed correctly on the .xhtml file.

The problem is that all the EL expressions of index.jsf page are not being processed/evaluated. No error is thrown but where I put #{myBean.property} is always being rendered as an empty String. Debugging it I see that the server code of my Managed bean is not being called.

I tried changing the el-api and el-impl libs for many versions, but no one worked. The final version I used is the el-api 2.2 specification, following the page https://myfaces.apache.org/core23/myfaces-impl/dependencies.html

As no error is being thrown, I can't figure out where is the problem. Does anybody has this error? Is it possible to run MyFaces 2.3 under a Spring Boot application packed as a jar file?

Here are the dependencies I am using on Gradle build file:

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    compile("org.jetbrains.kotlin:kotlin-reflect")

    testCompile group: 'junit', name: 'junit', version: '4.12'
    testCompile('org.springframework.boot:spring-boot-starter-test')

    compile 'io.github.microutils:kotlin-logging:1.5.4'

    compile group: 'org.apache.myfaces.core', name: 'myfaces-impl', version: '2.3.1'
    compile group: 'org.apache.myfaces.core', name: 'myfaces-api', version: '2.3.1'
    compile group: 'javax.enterprise', name: 'cdi-api', version: '2.0' //CDI vem embutido no JavaEE 6, mas não no Tomcat 9

    compile group: 'org.glassfish.web', name: 'el-impl', version: '2.2'

    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot
    compile 'org.springframework.boot:spring-boot-starter-web:2.0.3.RELEASE'
    compile 'org.apache.tomcat.embed:tomcat-embed-jasper:8.5.32'
    compile 'com.fasterxml.jackson.module:jackson-module-kotlin:2.9.6'
    compile group: 'org.ocpsoft.rewrite', name: 'rewrite-servlet', version: '3.4.2.Final'

}

Here is the Spring configuration, to load Faces servlets:

@Component
open class ConfigureJSF : ServletContextInitializer {
    private val logger = KotlinLogging.logger {}

    @Throws(ServletException::class)
    override fun onStartup(servletContext: ServletContext) {
        //necessary to myfaces be enabled and work in spring boot, once servlets are loaded dynamically.
        servletContext.setInitParameter("org.apache.myfaces.INITIALIZE_ALWAYS_STANDALONE", "true")

        servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", "true");
        servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", "true");

        servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml")
        servletContext.setInitParameter("javax.faces.FACELETS_REFRESH_PERIOD", "1")

        servletContext.setInitParameter("org.apache.myfaces.EXPRESSION_FACTORY", "com.sun.el.ExpressionFactoryImpl")
        servletContext.setInitParameter("org.apache.myfaces.CACHE_EL_EXPRESSIONS", "alwaysRecompile")

                    }

    // Register ServletContextListener, necessary for Myfaces.
    @Bean
    open fun listenerRegistrationBean1(): ServletListenerRegistrationBean<ServletContextListener> {
        val bean = ServletListenerRegistrationBean<ServletContextListener>()
        bean.setListener(org.apache.myfaces.webapp.StartupServletContextListener())
        return bean
    }

    @Bean
    fun requestContextListener(): RequestContextListener {
        return RequestContextListener()
    }

    //The faces servlet
    @Bean
    open fun facesServlet(): ServletRegistrationBean<MyFacesServlet> {
        logger.info { "Criando Faces Servlet..." }
        val servlet = org.apache.myfaces.webapp.MyFacesServlet() ;
        val servletRegistrationBean = ServletRegistrationBean(servlet, "*.jsf", "*.xhtml")
        servletRegistrationBean.setLoadOnStartup(1)
//        servletRegistrationBean.order = 1;
        return servletRegistrationBean;
    }

Edit:

I copied the dependency configuration of another project that works, and the same result occurred. So, the problem is not with the code I did paste here, and yes, with my environment, which I will start to investigate more detailed on the sequence. My problematic environment contains JDK 8, 9 and 10 and Tomcat 9. My project is targeting JDK 8. Maybe there is some incompatibility here and this is the reason for some compiled annotations not being found, I believe I will discover the problem very soon.

回答1:

After days trying to solve this problem, changing and combining different codes and environments, from JDK 8 to 10, Tomcat 8 and 9, testing in MacOS and Windows 10,from the JSF 2.1 implementation of MyFaces to the brand new JSF 2.3 implementation supporting CDI, deployed this last one on a WildFly server, I just noticed, on my expensive 32'' high-resolution display, that my Managed Bean was named with indexBeanusing a stranger character i with small dots on its top of, it was a diarised ï that I don't know how it had placed or typed there. That was the reason my managed bean was never found no matter what configuration I used.

I noticed this character on MacOS. On my Windows it seems harder to notice it. I think it's because of font differences, not hardware.

I am ashamed but I will not delete this question. May this can help someone in the future. Programming and life problems are like this: most of the times the error is in the less expected place.

Lesson learned.