JSF - Passing Parameters to a view on click of Button [duplicate] - jsf

This question already has answers here:
Creating master-detail pages for entities, how to link them and which bean scope to choose
(2 answers)
Closed 6 years ago.
I am using JSF 2.0 and have a simple TestButton.xhtml like below:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<ui:composition 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"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<h:body>
<h:form>
<h:inputText value="#{employee.empName}"/><br/>
<h:commandButton value="Derive" action="EmployeeTest2" >
<f:param name="Name" value="#{employee.empName}"/>
</h:commandButton>
</h:form>
</h:body>
</ui:composition>
And a Managed bean which is view scoped.
#ManagedBean(name="employee", eager=true)
#ViewScoped
public class Employee implements Serializable{
String empName;
String selectedEmployeeName;
public String getSelectedEmployeeName() {
return selectedEmployeeName;
}
public void setSelectedEmployeeName(String selectedEmployeeName) {
this.selectedEmployeeName = selectedEmployeeName;
}
public Employee() {
super();
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public void manipulate(){
System.out.println("Manipulate called...");
System.out.println(selectedEmployeeName);
this.selectedEmployeeName = this.selectedEmployeeName + " Jr.";
}
Now on click of button, i navigate to EmployeeTest2.xhtml which has following code :
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<ui:composition 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"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<f:view>
<f:metadata>
<f:viewParam name="Name" value="#{employee.selectedEmployeeName}"/>
<f:event type="preRenderView" listener="#{employee.manipulate}"/>
</f:metadata>
</f:view>
<h:body>
<h:inputText value="#{employee.selectedEmployeeName}"/>
</h:body>
</ui:composition>
i get correctly navigated to EmployeeTest2.xhtml but my parameter value is coming as null. I can see that manipulate method is getting called(sysouts get printed) but selectedEmployeeName is null.
Please advise as to what am i missing.
I already referred to below thread and did same but of no help.
https://stackoverflow.com/questions/20880027/passing-parameters-to-a-view-scoped bean-in-jsf
Update 1: Changed
<h:inputText value="Chris"/>
to
<h:inputText value="#{employee.empName}"/>
Put a breakpoint at setter method for selectedEmployee. Setter is not getting called which means param passing is not working.
Update 2 Please see updated testButton.xhtml
?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<ui:composition 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"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<h:body>
<h:form>
<h:inputText name = "Name" value="#{employee.empName}"/><br/>
<h:commandButton value="Submit" action="EmployeeTest2" >
<f:param name="Name" value="#{employee.empName}"/>
</h:commandButton>
</h:form>
</h:body>
</ui:composition>

The code seems correct, in my opinion you are sending null to the next page because the value of the employee.empName is actually null.
I would debug the getEmpName() method when the TestButton.xhtml is loaded and then additionally check, after you click the button and move on to the next page whether the parameter is present in the url.
UPDATE
Ok the param is actually the value of the input. In that case add name to its definition. You form should look like this:
<h:inputText name="Name" value="#{employee.empName}"/><br/>
<h:commandButton value="Derive" action="EmployeeTest2" />
UPDATE 2
This is a workaround but you can also try this:
#PostConstruct
public void postConstruct(){
Map<String,String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
setSelectedEmployeeName(params.get("Name"));
}

Related

Getter method returns null when called from action listener [duplicate]

This question already has answers here:
How to choose the right bean scope?
(2 answers)
Closed 4 years ago.
I have an application with a p:selectOneMenu component. This component is used to determine what category of file is being uploaded so I can do some work to it when the file is uploaded.
I implemented the answer from this post and it seems to call my setter methods correctly for fileType. But once the file is submitted and the handleFileUpload method is called, the fileType getter method returns null.
For example, if I select Foo then I get the output
File type changed to: Foo
But when I hit the upload button I get the output
The file type selected is null
When I expect
The file type selected is Foo
What is causing the get method to return two different results and is there a way to fix this?
main.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<meta http-equiv="refresh"
content="#{session.maxInactiveInterval};url=index.xhtml" />
<f:view contentType="text/html">
<h:head>
<title>File Upload</title>
</h:head>
<p:layout fullPage="true">
<p:layoutUnit position="center">
<ui:insert name="pagebody" />
</p:layoutUnit>
</p:layout>
</f:view>
</html>
index.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui" template="/templates/main.xhtml">
<ui:define name="pagebody">
<h:body>
<h:form id="uploadform" enctype="multipart/form-data">
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<h:outputText value="File Type:" />
<p:selectOneMenu value="#{uploadBean.fileType}">
<f:selectItem itemLabel="Foo" itemValue="Foo"/>
<f:selectItem itemLabel="Bar" itemValue="Bar"/>
<f:ajax listener="#{uploadBean.changeFileType}" />
</p:selectOneMenu>
</h:panelGrid>
<br />
<p:fileUpload fileUploadListener="#{uploadBean.handleFileUpload}" mode="advanced"/>
</h:form>
</h:body>
</ui:define>
</ui:composition>
UploadBean.java
#RequestScoped
#ManagedBean(name = "uploadBean")
public class UploadBean implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String fileType = null;
#PostConstruct
public void init() {
}
public void handleFileUpload(FileUploadEvent event){
System.out.println("The file type selected is " + this.getFileType());
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
public void changeFileType() {
System.out.println("File type changed to: " + this.getFileType());
}
}
As pointed out by #Kukeltje the issue was that my bean was not properly scoped. Switching from RequestScoped to ViewScoped fixed the issue I was having.

ui:param can't be evaluated in actionListener inside a composite component

If I pass an expression to a composite component like
<My:myButton action="#{bean.myaction()" value="#{bean.buttText()}"
and try to use it in
<cc:implementation>
<h:commandButton actionListener="#{cc.attrs.action} value="#{cc.attrs.value}...
I get the exception "Target Unreachable, identifier 'bean' resolved to null".
But only if bean is a <ui:param name="bean" value="#{myRealBean}"/> inside a template. The error only occours with actionListener. The button text, resolved from the same bean in the same way will be shown.
This old question seems to have the same problem but no answer.
If I split the parameter to
<My:myButton bean="#{bean}" method="myaction" value="#{bean.buttText()}"
and use
<cc:implementation>
<h:commandButton actionListener="#{cc.attrs.bean[cc.attrs.method]()} ...
no error occours and everything works fine.
How can I use a function-expression in an actionListener inside a composite component, where the bean is a <ui:param?
Glassfish 4.1.1, Mojarra 2.2.12
And now, the MCVE
a bean:
package beans;
import java.io.Serializable;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class Testbean implements Serializable {
public String getButtText() { return "Submit"; }
public void doAction() { System.out.println("Ajax was here."); }
}
a page
<!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:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ST="http://java.sun.com/jsf/composite/softeam" >
<h:head>
</h:head>
<h:body>
<h:form id="testform">
<h:panelGrid columns="1">
<ui:include src="testtemplate.xhtml">
<ui:param name="bean" value="#{testbean}"/>
</ui:include>
<ST:testButt text="#{testbean.buttText}" action="#{testbean.doAction()}"/>
<h:commandButton value="#{testbean.buttText}" actionListener="#{testbean.doAction()}"/>
</h:panelGrid>
</h:form>
</h:body>
</html>
and a template
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:ST="http://java.sun.com/jsf/composite/softeam">
<ST:testButt text="#{bean.buttText}" action="#{bean.doAction()}"/>
<h:commandButton value="#{bean.buttText}" action="#{bean.doAction()}" />
</ui:composition>
and the component
<!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:S="http://xmlns.jcp.org/jsf/composite" >
<S:interface>
<S:attribute name="action" method-signature="void action()"/>
<S:attribute name="text" type="java.lang.String"/>
</S:interface>
<S:implementation>
<h:commandButton style="display:inline-block"
value="#{cc.attrs.text}"
actionListener="#{cc.attrs.action}"
/>
</S:implementation>
</html>
All buttons will be shown (with the bean.buttText()) but only the second, third and fourth will call the action. The first button throws an exception when clicked.
Edit: Example reduced to JSF, no PrimeFaces components.

JSF2.0 composite component calling set method for a custom datatype

Greeting,
i have created a JSF composite component that takes an object of custom made class, and views its content, everything went good but i need the component to call the set method in the bean holding the custom class object.
Sample Example :
1- the component - componentTest.xhtml :
<?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:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="valueHolder" required="true" type="com.max.ValueHolder" />
</composite:interface>
<composite:implementation>
<h:inputText value="#{cc.attrs.valueHolder.value}" />
</composite:implementation>
</html>
notice that the component use an attribute of a custom type :
<composite:attribute name="valueHolder" required="true" type="com.max.ValueHolder" />
2- the test page - default.xhtml:
<?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:max="http://java.sun.com/jsf/composite/max" >
<h:body>
<h:form target="#self">
<max:componentTest valueHolder="#{user.valueHolder}" />
<h:commandButton value="test" action="#{myBean.action}" />
</h:form>
</h:body>
</html>
and finally the bean - MyBean.java :
package com.max;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import com.max.ValueHolder;
#ManagedBean(name="myBean")
#SessionScoped
public class MyBean{
private ValueHolder valueHolder= new ValueHolder();
public ValueHolder getValueHolder() {
return valueHolder;
}
public void setValueHolder(ValueHolder valueHolder) {
this.valueHolder = valueHolder;
}
public String action(){
return "default";
}
}
My problem is that the method Mybean.setValueHolder() is not being called as the h:inputText is holding the value within the ValueHolder not the ValueHolder itself.
and i have tried setting the value with something like
<c:set var="cachedValueHolder" value="${cc.attrs.valueHolder}"/>
<a4j:ajax event="change" >
<a4j:param value="#{cachedValueHolder}" assignTo="#{cc.attrs.valueHolder}" />
</a4j:ajax>
but it didnt work im not sure why!
Regards

Can't inject the selected value of a selectOneMenu in another bean

I was trying to see exactly how property injection works with ViewScoped beans.
I inject the List from One to Two without problem. When I try to inject the same List from Two to Three nothing is injected but I think that's the intended behavior (I might be wrong though).
However when I try to inject the selected value from the SelectOneMenu of Two into Three nothing is being injected.
Is there something I am missing or is that the normal behaviour? If so, how can I retrieve that value in Three?
One.java
#ManagedBean
#ViewScoped
public class One implements Serializable {
private List<String> oneList;
#PostConstruct
void init() {
setOneList(new ArrayList<String>());
getOneList().add("aaa");
getOneList().add("bbb");
getOneList().add("ccc");
getOneList().add("ddd");
}
//Getters + setters...
}
one.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="/WEB-INF/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:define name="header">
<h:outputText value="ONE" />
</ui:define>
<ui:define name="content">
<h:form>
<p:commandButton value="two" action="two" ajax="false" />
</h:form>
</ui:define>
</ui:composition>
Two.java
#ManagedBean
#ViewScoped
public class Two implements Serializable {
#ManagedProperty("#{one.oneList}")
private List<String> oneList;
private String twoChoice;
//Getter + setters...
}
two.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="/WEB-INF/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:define name="header">
<h:outputText value="TWO" />
</ui:define>
<ui:define name="content">
<h:form>
<p:selectOneMenu id="test" value="#{two.twoChoice}">
<f:selectItems value="#{two.oneList}" />
</p:selectOneMenu>
<p:commandButton value="three" action="three" ajax="false" />
</h:form>
</ui:define>
</ui:composition>
Three.java
#ManagedBean
#ViewScoped
public class Three implements Serializable {
#ManagedProperty("#{two.oneList}")
private List<String> oneList;
#ManagedProperty("#{two.twoChoice}")
private String twoChoice;
private String threeChoice;
//Getters + setters...
}
three.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="/WEB-INF/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:define name="header">
<h:outputText value="THREE" />
</ui:define>
<ui:define name="content">
<h:outputText value="#{three.twoChoice}" />
</ui:define>
<h:form>
<p:selectOneMenu value="#{three.threeChoice}">
<f:selectItems value="#{three.oneList}" />
</p:selectOneMenu>
</h:form>
</ui:composition>
Managed properties are not intended to work like that. Keep in mind that a #ViewScoped bean is designed to keep alive as long as the view doesn't change, which means at the moment you navigate from one page to another using the non-ajax command button (in fact you're specifying the navigation-case to go in the action attribute), they should be destroyed, so you can't get any value from them.
Normally, I use #ManagedProperty notation to inject broader scope values (for example, a session value in a view scoped bean). So what is the solution for your case?
Actually you have different options:
You can use <f:viewParam /> tag to send the GET parameters while changing the view.
You can use flash scope, which keeps your values in a map that survives to a redirection. Not recomended if you are using Mojarra implementation of JSF, they still have to fix some problems with them.
Take care of the params yourself and set them in some data structure in session scope, after, when you recover them in your destination bean you can remove them.

Trying to change <ui:include> src tag dynamically

I have main page that looks like this:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<p:panel id="panel">
<ui:include src="#{bean.page}">
</ui:include>
</p:panel>
<p:commandButton actionListener="#{bean.changePage}" value="Push" ajax="true" update="panel"/>
</h:form>
</h:body>
</html>
What I want to do is have a bean like this and change dynamically which page is included. This is how bean looks like:
#ManagedBean
#SessionScoped
public class Bean {
private String page = "";
public Bean() {
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public void changePage(ActionEvent e) {
page = "Page.xhtml";
}
}
When I click button Push I want this page to be included:
<?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:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<ui:component>
Hello from facelets
</ui:component>
</h:form>
</h:body>
Problem is that I have to press the button twice for page to be included. How can this be done so when I press the button the first time page is included?
This kind of templating is normally achieved using the <ui:insert> and <ui:define> tags. Check out this page of the Java EE tutorial.

Resources