Hello together, I mentioned that TomEE Plume 10 struggles to resolve the component type of a composite component, when restoring a view with multiple different composite components.
I created the following play example: On the page index.xhtml I am using two different composite components <cc:output1> and <cc:output2> with componentType "com.example.components.CompositeOutput1" and "com.example.components.CompositeOutput2" respectively. There also is a <h:commandButton> whose action method navigates back to the current page. <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="jakarta.faces.html" xmlns:cc="jakarta.faces.composite/taglib"> <h:body><h:form id="form"><cc:output1 id="output1" value="#{valueFace.value}"/><cc:output2 id="output2" value="#{valueFace.value}"/><h:commandButton value="submit" action="#{valueFace.increment}"/></h:form></h:body></html> The composite components consist of a .xhtml file: <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="jakarta.faces.html" xmlns:composite="jakarta.faces.composite"> <composite:interface componentType="com.example.components.CompositeOutput1"><composite:attribute name="value" required="true"/></composite:interface><composite:implementation><div id="#{cc.clientId}"> <h:outputText binding="#{cc.output1}"/></div> </composite:implementation></html> and a java class: @FacesComponent("com.example.components.CompositeOutput1") public class CompositeOutput1extends UIInputimplements NamingContainer { private UIOutputoutput1; @Override public StringgetFamily() { return UINamingContainer.COMPONENT_FAMILY; } @Override public void encodeBegin(FacesContext context)throws IOException { Object value = getValue(); this.output1.setValue(value); } public UIOutputgetOutput1() { return output1; } public void setOutput1(UIOutput output1) { this.output1 = output1; } } You can find the other required files attached. *Steps to reproduce:* 1. go to the page index.xhtml 2. click the submit button *Expected behavior:* When clicking the submit button, one should stay at the same page. The output values are incremented *Observed behavior:* When clicking the submit button, the following exception is thrown: jakarta.el.PropertyNotFoundException: Die Eigenschaft [output2] wurde für den Typ [com.example.components.CompositeOutput1] nicht gefunden jakarta.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:261) jakarta.el.BeanELResolver.property(BeanELResolver.java:330) jakarta.el.BeanELResolver.getType(BeanELResolver.java:82) com.sun.faces.el.DemuxCompositeELResolver._getType(DemuxCompositeELResolver.java:169) com.sun.faces.el.DemuxCompositeELResolver.getType(DemuxCompositeELResolver.java:194) org.apache.el.parser.AstValue.setValue(AstValue.java:191) org.apache.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:199) org.apache.webbeans.el22.WrappedValueExpression.setValue(WrappedValueExpression.java:92) com.sun.faces.facelets.el.ContextualCompositeValueExpression.setValue(ContextualCompositeValueExpression.java:126) com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:95) jakarta.faces.component.UIComponent.processEvent(UIComponent.java:1875) com.sun.faces.lifecycle.RestoreViewPhase.lambda$deliverPostRestoreStateEvent$0(RestoreViewPhase.java:381) com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:125) jakarta.faces.component.UIComponent.visitTree(UIComponent.java:1266) jakarta.faces.component.UIComponent.visitTree(UIComponent.java:1278) jakarta.faces.component.UIComponent.visitTree(UIComponent.java:1278) jakarta.faces.component.UIComponent.visitTree(UIComponent.java:1278) jakarta.faces.component.UIForm.visitTree(UIForm.java:344) jakarta.faces.component.UIComponent.visitTree(UIComponent.java:1278) jakarta.faces.component.UIComponent.visitTree(UIComponent.java:1278) com.sun.faces.lifecycle.RestoreViewPhase.deliverPostRestoreStateEvent(RestoreViewPhase.java:379) com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:223) com.sun.faces.lifecycle.Phase.doPhase(Phase.java:72) com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:96) com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:131) jakarta.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:691) jakarta.faces.webapp.FacesServlet.service(FacesServlet.java:449) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) org.apache.openejb.server.httpd.EEFilter.doFilter(EEFilter.java:67) The same error can be observed, if a composite component is used inside of another composite component. This behavior only occurs on TomEE Plume 10.0.0. It doesn't on TomEE Plus 10.0.0 and Wildfly 35. Is this a known issue? Is there a workaround? Defining the components in a taglib file did not solve the problem. Thank you for your help Kind regards Till Gräfenberg
index.xhtml
Description: application/xhtml
output1.xhtml
Description: application/xhtml
output2.xhtml
Description: application/xhtml
package com.example.faces; import jakarta.enterprise.context.SessionScoped; import jakarta.inject.Named; import java.io.Serializable; @Named("valueFace") @SessionScoped public class ValueFace implements Serializable { Integer value = 42; public Integer getValue() { return value; } public void setValue(Integer value) { this.value = value; } public void increment() { this.value = this.value + 1; } }
package com.example.components; import jakarta.faces.component.*; import jakarta.faces.context.FacesContext; import java.io.IOException; @FacesComponent("com.example.components.CompositeOutput1") public class CompositeOutput1 extends UIOutput implements NamingContainer { private UIOutput output1; @Override public String getFamily() { return UINamingContainer.COMPONENT_FAMILY; } @Override public void encodeBegin(FacesContext context) throws IOException { Object value = getValue(); this.output1.setValue(value); } public UIOutput getOutput1() { return output1; } public void setOutput1(UIOutput output1) { this.output1 = output1; } }
package com.example.components; import jakarta.faces.component.*; import jakarta.faces.context.FacesContext; import java.io.IOException; @FacesComponent("com.example.components.CompositeOutput2") public class CompositeOutput2 extends UIOutput implements NamingContainer { private UIOutput output2; @Override public String getFamily() { return UINamingContainer.COMPONENT_FAMILY; } @Override public void encodeBegin(FacesContext context) throws IOException { Object value = getValue(); this.output2.setValue(value); } public UIOutput getOutput2() { return output2; } public void setOutput2(UIOutput output) { this.output2 = output; } }