JSF ViewParams not being passed - jsf

I am finding view params will not be passed from a page where the backing bean is different on the target page. How can I pass the product param from test1.xhtml to test2.xhtml?
test.xhtml
<!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: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" xmlns:o="http://omnifaces.org/ui">
<body>
<f:metadata>
<o:viewParam name="product" value="#{holder.value}"
converter="#{productConverter}"
converterMessage="Bad request. Unknown product." required="true"
requiredMessage="Bad request. Please use a link from within the system." />
</f:metadata>
<h:link outcome="/test2.xhtml" includeViewParams="true">link</h:link>
</body>
</html>
test2.xhtml
<!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: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" xmlns:o="http://omnifaces.org/ui">
<h:head></h:head>
<body>
<f:metadata>
<o:viewParam name="product" value="#{holder2.value}"
converter="#{productConverter}"
converterMessage="Bad request. Unknown product." required="true"
requiredMessage="Bad request. Please use a link from within the system." />
</f:metadata>
<h:link outcome="/test.xhtml" includeViewParams="true">link</h:link>
</body>
</html>
Holder.java
#ManagedBean
#ViewScoped
public class Holder<T> implements Serializable {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
Holder2.java
#ManagedBean
#ViewScoped
public class Holder2<T> implements Serializable {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
Product.java
public class Product {
private String name;
public Product(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
}
Product Converter
public class ProductConverter implements Converter {
private Map<String,Product> productMap=new HashMap<String, Product>();
public ProductConverter(List<Product> products) {
for (Product product:products){
productMap.put(product.getName().toLowerCase(), product);
}
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return productMap.get(value.toLowerCase());
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (!(value instanceof Product) ) {
return null;
}
return ((Product) value).getName().toLowerCase();
}
}

<h:link outcome="/test2.xhtml?includeViewParams=true">link</h:link>
This is not the right way to let JSF include view parameters in a <h:link>. Supplying it as a query string parameter is only valid in action attribute of UICommand components.
You need the includeViewParams attribute of the <h:link> instead.
<h:link outcome="/test2.xhtml" includeViewParams="true">link</h:link>

#ViewScoped is only valid for postbacks - if you change the URL, the bean dies.
To pass parameters between facelets, use <ui:param>

Related

JSF viewParam not set

xhtml file I use a viewParam:
<?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"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<f:metadata>
<f:viewParam name="actionId" value="#{editActionView.actionId}" required="true" />
</f:metadata>
<h:body>
The backing bean looks as follows:
EditActionView.java
#ManagedBean
#ViewScoped
public class EditActionView {
private long actionId;
#PostConstruct
void init() {
System.out.println("actionId: " + getActionId());
}
public long getActionId() {
return actionId;
}
public void setActionId(long actionId) {
this.actionId = actionId;
}
When I now call my application:
http://localhost:8080/aip/editAction.jsf?actionId=37
actionId is always 0. Where is my fault?
The ManagedBean is constructed before the setter is called. Therefore the System.out.println(...) in the #PostConstruct method prints the default value for the actionId of type long which is 0.
The setter is then called in the UPDATE_MODEL_VALUES phase. You can check this by putting another System.out.println(...) in the setter method, which should print the correct value.

Passing parameter between pages

I'm unable to pass a simple parameter from one Facelet to another, and set a bean property...here's my code:
The calling page, main.xhtml (only relevant code):
<h:link outcome="index" value="disconnect" >
<f:param name="logout" value="true" />
</h:link>
The final page, index.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:f="http://xmlns.jcp.org/jsf/core">
<f:metadata>
<f:viewParam name="logout" value="#{indexBean.logout}"/>
<f:event type="preRenderView" listener="#{indexBean.redirect}" />
</f:metadata>
</html>
And the IndexBean (only relevant code):
#Named
#RequestScoped
public class IndexBean {
#Inject
private Logger logger;
private boolean logout;
public IndexBean() {this.logout = false;}
public void setLogout(boolean logout) {
logger.log(Level.DEBUG, "logout changed");
this.logout = logout;
}
public boolean isLogout() {return logout;}
public void redirect() throws IOException {
if(logout) {
//Never get in here
} else {
//Always here
}
}
}
I'm getting the URL parameter right on the link (http://localhost/index.xhtml?logout=true), but the setLogout method is never called.
I've even tried to change the logout type to String, change getter and setter properly and see what happens, but the setter is never called...
Any idea?
Thanks in advance!!

ManagedBean with ArrayList, how to add elements?

I'm trying to do SIMPLE webapp which show partyguest list and allow me to add new guest. I want to store guests in ArrayList. I don't know where and how to invoke party.addGuest() method.
index.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://xmlns.jcp.org/jsf/html">
<h:head>
<title>Big Party</title>
</h:head>
<h:body>
<h2>Add new guest to Big Party: </h2>
<h:form>
<h:inputText id="guestName" value="#{guest.name}"/>
<h:commandButton value="Add guest" action="guests" />
</h:form>
<h:link value="GuestList" outcome="guests" />
</h:body>
</html>
guests.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://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>Super Party</title>
</h:head>
<h:body>
<h2>New guest:</h2>
<h:outputLabel value="#{guest.name}" />
<h2>Guests:</h2>
<ul>
<ui:repeat value="#{party.guests}" var="curr">
<li>#{curr}</li>
</ui:repeat>
</ul>
<h2>Guests count:</h2>
<h:outputLabel value="#{party.cnt}"/>
</h:body>
</html>
Party.java
package managedBeans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
#ManagedBean(name = "party")
#ApplicationScoped
public class Party implements Serializable {
private List<String> guests;
private int cnt;
public Party() {
}
#PostConstruct
public void init() {
guests = new ArrayList<>();
guests.add("Guest A");
guests.add("Guest B");
}
public List<String> getGuests() {
return guests;
}
public void addGuest(String guest) {
guests.add(guest);
}
public int getCnt() {
cnt = guests.size();
return cnt;
}
}
Guest.java
package managedBeans;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean(name = "guest")
#RequestScoped
public class Guest implements Serializable{
private String name;
public Guest() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
If you are using JSF 2, you can have something like this in your index.xhtml (but it can be easily converted to earlier JSF version):
...
<h:form>
<h:inputText id="guestName" value="#{party.newGuest}"/>
<h:commandButton value="Add guest" action="#{party.addGuest()}" />
</h:form>
...
And, in Party.java:
private String newGuest;
....
public String getNewGuest() {
return this.newGuest;
}
public void setNewGuest(String guest) {
this.newGuest = guest;
}
....
public void addGuest() {
guests.add(newGuest);
newGuest = null;
}
No need for Guest.java in this use case. Could be done in a nicer way, though.

invoke method of #facescomponent of composite component

I need to invoke a method of backing component(#facescomponent) of composite component. I see others do this in articles but none of them has ever worked for me.
this how I invoke:
<ui:component 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:cc="http://java.sun.com/jsf/composite">
<cc:interface componentType="formField"/>
<cc:implementation>
<h:commandButton value="doIt" action="#{cc.myAction}" ></h:commandButton>
</cc:implementation>
</ui:component>
and this is the backing component.
#FacesComponent("formField")
public class Field extends UICommand implements NamingContainer {
public Field() {
}
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
public String myAction() {
System.out.println("in action");//not printed
return null;
}
}
Shouldn't myAction method be invoked? What did I do wrong?
you do an invoke for property, for method need to use:
action="#{cc.myAction()}"

How to print ArrayList in JSF Facelets

I have been trying to print the values from an ArrayList<String> in JSF Facelets, but with no luck. The value is getting stored in an ArrayList but the output is blank on the page.
Bean file:
import java.io.Serializable;
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
#ManagedBean(name="newCompanyName")
#SessionScoped
public class CompanyNames implements Serializable {
private static final long serialVersionUID = 1L;
private ArrayList<String> list = new ArrayList<String>();
private String companyName;
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
list.add(companyName);
System.out.println("Size of array list is : "+list.size());
for (String number : list) {
System.out.println("Number = " + number);
}
}
public CompanyNames(String companyName) {
this.companyName = companyName;
}
public CompanyNames() {
}
}
Here is my JSF file from an XHTML 1.0 Transitional file:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
</h:head>
<h:body>
<ui:repeat var="item" value="#{CompanyNames.list}">
<h1>#{item}</h1>
</ui:repeat>
</h:body>
</html>
Instead of
<ui:repeat var="item" value="#{CompanyNames.list}"> <h1>#{item}</h1> </ui:repeat>
use
<ui:repeat var="item" value="#{newCompanyName.list}"> <h1>#{item}</h1> </ui:repeat>
You will also need a getList method for the class CompanyNames
public List<String> getList() {
return this.list;
}
Use companyNames.list instead of CompanyNames.list and you will also need the get() function of list.

Resources