Summary
GroupRenderer decides whether to emit a wrapper element (div/span) around h:panelGroup based on too narrow a gate. It should also emit the wrapper when the component carries any passthrough attribute or an attached client behavior — matching MyFaces and the rendering contract just clarified in the Faces spec.
Background
Jakarta Faces jakartaee/faces#2182 found that the four normative doc sources for the jakarta.faces.Group renderer contradicted each other and reality. jakartaee/faces#2186 (targeting 5.0) resolved this doc-only, standardizing on the broader MyFaces "any renderable attribute" gate as the specified minimum:
A wrapper element is rendered when the component has a renderable client id, or any renderable attribute is present (style, styleClass, any passthrough attribute, or an attached client behavior). When a wrapper element is rendered, a value of "block" for the layout attribute produces a div; any other value (or an absent layout) produces a span.
This issue is the Mojarra impl counterpart of that doc change.
Current behavior
GroupRenderer.divOrSpan gates the wrapper on id / style / styleClass only:
private boolean divOrSpan(UIComponent component) {
return shouldWriteIdAttribute(component)
|| component.getAttributes().get("style") != null
|| component.getAttributes().get("styleClass") != null;
}
So a panelGroup that carries a passthrough attribute or an attached behavior but no id/style/styleClass emits no wrapper — yet encodeBegin still calls RenderKitUtils.renderPassThruAttributes(...), so those attributes (and behavior hooks) have no element to land on. Examples that misbehave today:
<h:panelGroup onclick="..."> / role, dir, lang, title, …
<h:panelGroup><f:passThroughAttribute name="data-x" value="y"/></h:panelGroup>
<h:panelGroup><f:ajax event="click" .../></h:panelGroup>
These would only work in Mojarra if the <h:panelGroup> has an explicit id, styleClass or style attribute.
Reference impl
MyFaces HtmlGroupRendererBase.encodeEnd already gates on the broader condition: renderable id, non-empty behaviors, or any passthrough/universal attribute present.
Proposed fix
Widen divOrSpan so it also returns true when the component has any renderable passthrough attribute or an attached client behavior, then div vs span selection by layout proceeds as today. File: impl/src/main/java/org/glassfish/mojarra/renderkit/html_basic/GroupRenderer.java.
Out of scope
Treating an explicit layout as an unconditional box trigger (so <h:panelGroup layout="block"/> always emits an empty div) is a separate behavior change requiring an EG decision and a spec version gate — see option (a) in jakartaee/faces#2182. Not part of this issue.
Summary
GroupRendererdecides whether to emit a wrapper element (div/span) aroundh:panelGroupbased on too narrow a gate. It should also emit the wrapper when the component carries any passthrough attribute or an attached client behavior — matching MyFaces and the rendering contract just clarified in the Faces spec.Background
Jakarta Faces jakartaee/faces#2182 found that the four normative doc sources for the
jakarta.faces.Grouprenderer contradicted each other and reality. jakartaee/faces#2186 (targeting 5.0) resolved this doc-only, standardizing on the broader MyFaces "any renderable attribute" gate as the specified minimum:This issue is the Mojarra impl counterpart of that doc change.
Current behavior
GroupRenderer.divOrSpangates the wrapper on id / style / styleClass only:So a panelGroup that carries a passthrough attribute or an attached behavior but no id/style/styleClass emits no wrapper — yet
encodeBeginstill callsRenderKitUtils.renderPassThruAttributes(...), so those attributes (and behavior hooks) have no element to land on. Examples that misbehave today:<h:panelGroup onclick="...">/role,dir,lang,title, …<h:panelGroup><f:passThroughAttribute name="data-x" value="y"/></h:panelGroup><h:panelGroup><f:ajax event="click" .../></h:panelGroup>These would only work in Mojarra if the
<h:panelGroup>has an explicitid,styleClassorstyleattribute.Reference impl
MyFaces
HtmlGroupRendererBase.encodeEndalready gates on the broader condition: renderable id, non-empty behaviors, or any passthrough/universal attribute present.Proposed fix
Widen
divOrSpanso it also returnstruewhen the component has any renderable passthrough attribute or an attached client behavior, thendivvsspanselection bylayoutproceeds as today. File:impl/src/main/java/org/glassfish/mojarra/renderkit/html_basic/GroupRenderer.java.Out of scope
Treating an explicit
layoutas an unconditional box trigger (so<h:panelGroup layout="block"/>always emits an emptydiv) is a separate behavior change requiring an EG decision and a spec version gate — see option (a) in jakartaee/faces#2182. Not part of this issue.