I have a JSF 2 master template as follows:
<!DOCTYPE html>
<html lang="#{localeManager.language}"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view locale="#{localeManager.locale}">
<h:head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title><ui:insert name="title">Default Title.</ui:insert></title>
<!-- Development Stylesheets -->
<ui:fragment rendered="#{facesContext.application.projectStage eq 'Development'}">
<h:outputStylesheet name="css/bootstrap.css" library="bootstrap" />
<h:outputStylesheet name="css/font-awesome.css" library="fontawesome" />
</ui:fragment>
<h:outputStylesheet name="css/main.css" library="core" />
<ui:insert name="header-stylesheet" />
<!-- Production Stylesheets -->
<ui:fragment rendered="#{facesContext.application.projectStage eq 'Production'}">
<h:outputStylesheet name="css/bootstrap.min.css" library="bootstrap" />
<h:outputStylesheet name="css/font-awesome.min.css" library="fontawesome" />
</ui:fragment>
<ui:insert name="header-script" />
</h:head>
<h:body>
<div id="wrapper">
<div id="header">
<ui:insert name="header">Default content</ui:insert>
</div>
<div id="body">
<ui:insert name="body">Default body</ui:insert>
</div>
<div id="footer">
<ui:insert name="footer">Default footer</ui:insert>
</div>
</div>
<!-- Development Scripts -->
<ui:fragment rendered="#{facesContext.application.projectStage eq 'Development'}">
<h:outputScript name="jquery-2.1.4.js" library="jquery" />
<h:outputScript name="js/bootstrap.js" library="bootstrap" />
</ui:fragment>
<!-- Production Scripts -->
<ui:fragment rendered="#{facesContext.application.projectStage eq 'Production'}">
<h:outputScript name="jquery-2.1.4.min.js" library="jquery" />
<h:outputScript name="js/bootstrap.min.js" library="bootstrap" />
</ui:fragment>
<ui:insert name="body-script" />
</h:body>
</f:view>
</html>
When deploying it in Wildfly 9.0.1 Final, I see that all my <ui:fragment>
attribute gets rendered. Why is that? I am developing using JSF 2.2 framework.
My Faces Project stage is Development
.
Note: Of all the answers in SO concerning this issue, none is the solution to this problem (so I did my homework).
The <h:outputStylesheet>
and <h:outputScript>
are special components. They will during view build time already add the declared stylesheet or script resource to the view via UIViewRoot#addComponentResource()
(see Mojarra source code here).
This is regardless of the rendered
condition of the component or its parents. In effects, they are basically relocated to the very end of the <h:head>
or the <h:body>
, depending on the value of target
attribute, causing them to not sit inside <ui:fragment>
anymore.
Then, during rendering, only their own rendered
attribute is considered (and actually also of <h:head>
, but that's pointless).
You have 2 options:
Use a view build time tag to conditionally add them to the view. The project stage condition is application scoped anyway.
<!-- Development Stylesheets -->
<c:if test="#{facesContext.application.projectStage eq 'Development'}">
<h:outputStylesheet ... />
<h:outputStylesheet ... />
</c:if>
<!-- Production Stylesheets -->
<c:if test="#{facesContext.application.projectStage eq 'Production'}">
<h:outputStylesheet ... />
<h:outputStylesheet ... />
</c:if>
Check the condition in component resource's own rendered
attribute. Use if necessary <c:set>
to create a short EL variable.
<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />
<!-- Development Stylesheets -->
<h:outputStylesheet ... rendered="#{dev}" />
<h:outputStylesheet ... rendered="#{dev}" />
<!-- Production Stylesheets -->
<h:outputStylesheet ... rendered="#{not dev}" />
<h:outputStylesheet ... rendered="#{not dev}" />