cyanotyp
cyanotyp

Reputation: 23

Jakarta Faces 4 / TomEE 10 - Nested composites, same attribute name causes StackoverflowError

We migrate from TomEE 9 to TomEE 10, and the Faces 4.0 part causes us troubles. We have nested composite components, which is allowed by design also according to composite components spec. Both have the same attribute name "responsiveScrollHeight".

Outer component (reduced to minimum to describe the topic) :

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:composite="jakarta.faces.composite"
      xmlns:lop="jakarta.faces.composite/lop">
<composite:interface>
    <composite:attribute name="responsiveScrollHeight" type="java.lang.Boolean" />
</composite:interface>
<composite:implementation>
    <f:subview id="outer">
        ...
        <lop:myComponent responsiveScrollHeight="#{cc.attrs.responsiveScrollHeight}"/>
        ..
    </f:subview>
</composite:implementation>    

inner component: myComponent

<composite:interface>
   <composite:attribute name="responsiveScrollHeight" type="java.lang.Boolean" />
</composite:interface>
<composite:implementation>
    <f:subview id="inner">
        <p:dataTable .. scrollHeight="#{cc.attrs.responsiveScrollHeight}" />
 </f:subview>
</composite:implementation>

In TomEE 9 it worked without problems.
In TomEE 10 this now leads to a StackoverflowError during EL resolving, at various places, always similar message like:

java.lang.StackOverflowError
at com.sun.faces.component.CompositeComponentStackManager.findCompositeComponentUsingLocation 
at com.sun.faces.facelets.el.ContextualCompositeValueExpression.pushCompositeComponent

The interesting part: as soon as I change the attribute name for the inner or outer component, e.g. to responsiveScrollHeight_inner it works again - would be a work-around which we do not want to go since our application has a lot of those components

So with me it seems the EL resolver in TomEE 10 runs into an infinite loop where TomEE 9 could resolve it. I checked here Differences in composite components behaviour when switching from JSF 2.2 to Jakarta Faces 4.0 and BalusC blog and migration guides and did not find a solution up to now.

Upvotes: 1

Views: 98

Answers (1)

BalusC
BalusC

Reputation: 1109192

This is caused by a change in resolving the #{cc} variable in EL context.

Previously, before Faces 4.0, this was done using an EL resolver. See also section "5.6.2.1. Implicit Object ELResolver for Facelets and Programmatic Access" of Faces 3.0 spec. Since Faces 4.0, this was done using a CDI producer instead. See also section "5.6.2.1. Implicit Objects for Facelets and Programmatic Access" of Faces 4.0 spec. It's classified as having a "dependent" scope in CDI, meaning it is supposed to be re-evaluated upon every access as per section 2.5.4. "Dependent pseudo-scope" of the CDI 4.0 spec.

Unfortunately, this is not working as intended when using OpenWebBeans as CDI implementation. For some reason it caches dependent instances in the EL context. This will go wrong when the #{cc} of the outer composite component is being referenced from within an inner composite component in case of a nested composite component. This was first reported as Mojarra issue 5515.

Already during the Faces 4.0 work I remember that we had our doubts whether #{cc} (and #{component}) should be produced by CDI and whether the "dependent" scope is absolutely the correct one for the desired behavior. In retrospect it appears it's most probably not correct. The CDI spec in turn is not crystal clear on the desired behavior of @Dependent when the recipient is not a CDI bean.

As per Mojarra 4.0.10 the #{cc} resolution will be done by an EL resolver instead of CDI producer. This should fix your problem. The Faces 5.0 spec will also be adjusted on this.

Upvotes: 1

Related Questions