jsfjakarta-eeapache-tomee

Jakarta Faces 4 / TomEE 10 - request not available in Expression Language


We migrate from TomEE 9 to TomEE 10, and the Faces 4.0 part causes us troubles. We already use faces-4.0.10-snapshot library due to a patched composite component issue. It seems that the "#{request}" is not available as Implicit Object in Expression Language, but "facesContext", "externalContext" and similar are available as described in https://jakarta.ee/specifications/faces/4.0/jakarta-faces-4.0#a2830 "5.6.2.1. Implicit Objects for Facelets and Programmatic Access". It seems the other ones are available and work - which would be also a "working but not so nice" work-around e.g.

#{externalContext.request.contextPath} - works
#{facesContext.externalContext.requestContextPath} - works
#{facesContext.externalContext.request.contextPath} - works

to debug it, I tried below line, which gives the same class as in TomEE 9

#{request.toString()} = org.apache.catalina.core.ApplicationHttpRequest@37482850

But finally

<h:outputText value="request.contextPath=#{request.contextPath}"/>

gives below exception (property contextPath not found for type...)

SEVERE org.primefaces.application.exceptionhandler.PrimeExceptionHandler * Die Eigenschaft [contextPath] wurde für den Typ [org.apache.webbeans.custom.Object$$OwbNormalScopeProxy6949990480] nicht gefunden
jakarta.el.PropertyNotFoundException: Die Eigenschaft [contextPath] wurde für den Typ [org.apache.webbeans.custom.Object$$OwbNormalScopeProxy6949990480] nicht gefunden
    at jakarta.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:261)
    at jakarta.el.BeanELResolver.property(BeanELResolver.java:330)
    at jakarta.el.BeanELResolver.getValue(BeanELResolver.java:99)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:139)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:164)
    at org.apache.el.parser.AstValue.getValue(AstValue.java:161)
    at org.apache.el.parser.AstDeferredExpression.getValue(AstDeferredExpression.java:42)
    at org.apache.el.parser.AstCompositeExpression.getValue(AstCompositeExpression.java:47)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:152)
    at org.apache.webbeans.el22.WrappedValueExpression.getValue(WrappedValueExpression.java:67)

Possible related topics and bug reports:


Solution

  • This has been fixed in Mojarra 4.0.11 as per issue 5561.

    It appears there's confusion in CDI wrt the purpose of Bean#getBeanClass():

    The bean class of the managed bean or session bean or of the bean that declares the producer method or field.

    In Faces, the #{request}, #{session}, etc are produced by CDI producers. So the getBeanClass() returns the class of the bean class having the producer method. This works fine in Weld, the reference implementation of CDI. However, it unfortunately doesn't work in OpenWebBeans, the alternative implementation of CDI.

    See also issue 5457. Right now Mojarra basically does this in CdiProducer in order to satisfy the both CDI implementations:

    protected CdiProducer<T> beanClass(BeanManager beanManager, Class<?> beanClass) {
        if (CdiUtils.isWeld(beanManager)) {
            this.beanClass = CdiExtension.class; // See #5457 and #5157
        } else {
            this.beanClass = beanClass;
        }
    
        return this;
    }