mojarra
mojarra copied to clipboard
Programmatic View with UIOutput
Sorry to post this here but I can't seem to find in the spec what is the correct behavior between MyFaces and Mojarra.
Original report: https://github.com/melloware/quarkus-faces/issues/444
When creating a programmatic view with the following code:
package org.apache.myfaces.core.extensions.quarkus.showcase.view;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.faces.annotation.View;
import jakarta.faces.application.StateManager;
import jakarta.faces.component.UIComponent;
import jakarta.faces.component.UIOutput;
import jakarta.faces.component.html.HtmlBody;
import jakarta.faces.component.html.HtmlCommandButton;
import jakarta.faces.component.html.HtmlForm;
import jakarta.faces.component.html.HtmlOutputText;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.facelets.Facelet;
@View("/facelet.xhtml")
@ApplicationScoped
public class FaceletView extends Facelet
{
@Override
public void apply(FacesContext facesContext, UIComponent parent)
{
if (!facesContext.getAttributes().containsKey(StateManager.IS_BUILDING_INITIAL_STATE))
{
return;
}
var components = new ComponentBuilder(facesContext);
var rootChildren = parent.getChildren();
var doctype = new UIOutput();
doctype.setValue("<!DOCTYPE html>");
rootChildren.add(doctype);
var htmlTag = new UIOutput();
htmlTag.setValue("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
rootChildren.add(htmlTag);
HtmlBody body = components.create(HtmlBody.COMPONENT_TYPE);
rootChildren.add(body);
HtmlForm form = components.create(HtmlForm.COMPONENT_TYPE);
form.setId("form");
body.getChildren().add(form);
HtmlOutputText message = components.create(HtmlOutputText.COMPONENT_TYPE);
message.setId("message");
HtmlCommandButton actionButton = components.create(HtmlCommandButton.COMPONENT_TYPE);
actionButton.setId("button");
actionButton.addActionListener(
e -> message.setValue("Hello, World! Welcome to Faces 4.0 on Jakarta EE 10"));
actionButton.setValue("Greet");
form.getChildren().add(actionButton);
parent.getChildren().add(message);
htmlTag = new UIOutput();
htmlTag.setValue("</html>");
rootChildren.add(htmlTag);
}
private static class ComponentBuilder
{
FacesContext facesContext;
ComponentBuilder(FacesContext facesContext)
{
this.facesContext = facesContext;
}
@SuppressWarnings("unchecked")
<T> T create(String componentType)
{
try
{
return (T) facesContext.getApplication().createComponent(componentType);
}
catch (ClassCastException e)
{
throw new IllegalArgumentException("Component type " + componentType + " is not valid.", e);
}
}
}
}
Attached is the reproducer: programmatic_view.zip
Run mvn clean jetty:run -Pmojarra40 and go to http://localhost:8080/facelet.xhml and Mojarra does this
Run mvn clean jetty:run -Pmyfaces40 and go to http://localhost:8080/facelet.xhml and MyFaces does this
the question comes down to "who is doing the right thing"? MyFaces seems to escape the following code but Mojarra does not
var htmlTag = new UIOutput();
htmlTag.setValue("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
rootChildren.add(htmlTag);
OK according to this MyFaces is doing the right thing and Mojarra is not.
https://github.com/jakartaee/faces/issues/1796
Not sure. See comment over there.