Consolidate several trivial JSF Views - jsf

I'm new to JSF, so please forgive me if I'm asking a stupid question.
Suppose I have a common.xhtml file that can be reused by several screens. In fact, the only difference between the screens is the backing bean. For example:
URL: ~/person
<ui:composition template="common.xhtml">
<ui:param name="bean" value="#{personBean}" />
</ui:composition>
URL: ~/vehicle
<ui:composition template="common.xhtml">
<ui:param name="bean" value="#{vehicleBean}" />
</ui:composition>
URL: ~/location
<ui:composition template="common.xhtml">
<ui:param name="bean" value="#{locationBean}" />
</ui:composition>
URL: ~/food
<ui:composition template="common.xhtml">
<ui:param name="bean" value="#{foodBean}" />
</ui:composition>
etc...
Is there a way I can avoid creating all of these trivial xhtml files? Can I somehow dynamically set the backing bean and just point each of these URLs directly to the common.xhtml file?

Related

How can I switch between two ui:compositions in a Facelets file?

In a JSF xhtml file, I would like to be able to choose between two different ui:compositions based on some flag. This is illustrated below using a fictional magic:if tag. How can I do this? In other words, what real tag can I use in place of magic:if?
<magic:if test="showOption1">
<ui:composition template="/option1.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:composition>
</magic:if>
<magic:if test="!showOption1">
<ui:composition template="/option2.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:composition>
</magic:if>
In other words, what real tag can I use in place of magic:if?
There's none. The <ui:composition> is the root element. Nothing can end up higher.
You have 2 options:
Do the switch in template attribute itself.
<ui:composition template="/option#{showOption1 ? 1 : 2}.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:composition>
Use <ui:decorate> inside <ui:composition> instead, this one can be wrapped in a <c:if>.
<ui:composition template="/options.xhtml">
<c:if test="#{showOption1}">
<ui:decorate template="/option1.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:decorate>
</c:if>
<c:if test="#{not showOption1}">
<ui:decorate template="/option2.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:decorate>
</c:if>
</ui:composition>

JSF 1.2: dynamic <ui:param />

There are some answers on stackoverflow, but no one fits my needs :(
I'm trying to conditionally build a <ui:param /> for my parent template with JSTL. Something like this:
<ui:composition ... template="template.xhtml">
<c:if test="#{condition}">
<ui:param name="parameter" value="parameterValue" />
</c:if>
<ui:define name="insertName">
{...}
</ui:define>
</ui:composition>
I tried with both namespaces for JSTL: http://java.sun.com/jstl/core and http://java.sun.com/jsp/jstl/core, but neither achieves the wanted behaviour. What should I do?
Funny thing, http://java.sun.com/jstl/core works like it should but INSIDE the <ui:define ...>
Im working with JSF 1.2 on WebLogic 7.

Command for autoload [duplicate]

This question already has answers here:
Invoke JSF managed bean action on page load
(4 answers)
Closed 7 years ago.
Is there an autoload command within JSF or PrimeFaces?
I have a JSF template that I use for my facelets:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="template.xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:form>
<p:remoteCommand name="onload" action="#{mainMenuBean.setMenuCategories}" autoRun="true" />
</h:form>
<ui:define name="west">
<ui:include src="mainmenu.xhtml" />
</ui:define>
<ui:define name="center">
<p:outputLabel value="Zentrum" />
<h:form>
<p:remoteCommand name="rc" update="msgs" actionListener="#{mainMenuBean.setMenuCategories()}" />
<p:growl id="msgs" showDetail="true" />
<p:commandButton type="button" onclick="rc()" value="Execute" icon="ui-icon-refresh" />
</h:form>
</ui:define>
</ui:composition>
Now the p:remoteCommand does not work for some reason. Is there are command that I could place instead of p:remoteCommand to automatically execute some bean method everytime it gets loaded?
JSF 2.2 has viewAction, which can be executed on each load or on each get (and skipped on postbacks). It's placed in meta part of page:
<f:meta>
<f:viewAction action="#{anyBean.anyAction}"/>
</f:meta>
edit: mind that this is an action component, so it's execution will depend on any preceding validations / conversions being successful.

Getting page parameters for a requestscoped bean in a form

I have the following page:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Fire - Registration</title>
</h:head>
<h:body>
<f:view>
<f:event type="preRenderView" listener="#{confirmPasswordResetBean.bindSessionKey()}"/>
</f:view>
<p:growl id="growl" showDetail="true" life="5000" />
<h:form>
<p:panel header="Select your new password">
<h:panelGrid columns="2" cellpadding="5">
<p:outputLabel for="newPassword" value="Type your new password"/>
<p:password id="newPassword"
value="#{confirmPasswordResetBean.firstPassword}"
feedback="true"/>
<p:outputLabel for="retypedPassword" value="Retype your password"/>
<p:password id="retypedPassword"
value="#{confirmPasswordResetBean.secondPassword}"/>
</h:panelGrid>
<p:commandButton id="confirmButton"
value="reset"
action="#{confirmPasswordResetBean.doResetPassword()}"
update=":growl"/>
</p:panel>
</h:form>
</h:body>
The backing bean used above is RequestScoped, and the page itself takes a single parameter (sessionKey)...what I want to do is to:
1. Bind sessionKey to a variable in the backing bean. This is straightforward enough.
2. Use the bound value of sessionKey when executing dedicated logic in the same bean, when the client presses the commandButton.
The problem is that pressing the button starts a new request, which invalidates both the current bean (with the bound value), as well as the external page context...I thus lose all means to get a hold of sessionKey from either the bean or the page parameters...how can I resolve this? I am relatively new to both web programming and JSF, so pardon me if this has an obvious answer.
Either put the bean in the view scope, so that it lives long as you're interacting with the same view, or pass the request parameter by <f:param> to the subsequent requests.
<p:commandButton ...>
<f:param name="sessionKey" value="#{param.sessionKey}" />
</p:commandButton>
By the way, you'd rather have used <f:viewParam> to bind the request parameter to the bean directly.
<f:metadata>
<f:viewParam name="sessionKey" value="#{bean.sessionKey}" />
</f:metadata>
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?

facelets: passing bean name with ui:param to action attribute

Due to some custom components which expect a bean name (NOT the bean instance) in their attributes I need to pass the actual bean name between pages. As the bean itself is also used by non-custom components, I would like to avoid using additional ui:param (like described here Passing action in <rich:modalPanel>) since it will essentially specify the same bean.
Is it possible to specify component's action using bean name provided with ui:param?
Basically I am trying to achieve the following:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="/template.xhtml">
<ui:param name="beanName" value="sessionBean"/>
...
</ui:composition>
and template.xhtml is
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j"
template="/someothertemplate.xhtml">
</ui:define name="somename">
<h:form>
<a4j:commandButton value="test" action="#{beanName.delete}"/>
</h:form>
</ui:define>
</ui:composition>
Although delete method is properly defined (verified with action="#{sessionBean.delete}") the above code gives me
javax.faces.FacesException: #{beanName.delete}: javax.el.MethodNotFoundException: /template.xhtml #201,89 action="#{beanName.delete}": Method not found: sessionBean.delete()
You should be able to reference the bean via its scope:
<a4j:commandButton value="test"
action="#{sessionScope[beanName].delete}"/>
<a4j:commandButton value="test" action="#{bean[action]}" />
The params to pass
<ui:param name="bean" value="#{sessionBean}" />
<ui:param name="action" value="delete" />
you can use #{bean['delete']} if your action name is fixed.

Resources