Setting bean's attribute - jsf

I'm building a simple e-shop with JSF. There is a page with a list of all the products (product-list.xhtml) and then a detail page for each product (product.xhtml). product-list.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"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
</h:head>
<h:body>
<f:view>
<h:outputText value="Number of items in the cart: #{shoppingCart.numberOfSelectedProducts}"/>
<h:link value="Cart" outcome="cart.xhtml"/>
<h:dataTable value="#{productController.products}" var="p">
<h:column>
#{p.name}
<h:commandLink action="product.xhtml" value="Detail">
<f:actionListener target="#{product.id}" value="#{p.id}"/>
</h:commandLink>
</h:column>
<h:column>
</h:column>
</h:dataTable>
</f:view>
</h:body>
</html>
then the product.xhtml looks following:
<?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"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<head></head>
<!--f:metadata>
<f:event type="preRenderView" listener="#{shoppingCart.loadSelectedProduct(param.id)}"/>
</f:metadata -->
<body>
<f:view>
<h:graphicImage value="resources/images/img.jpg"/>
<h:outputLabel value="The value of shoppingCart.selectedProduct is: #{shoppingCart.selectedProduct.id}"/>
</f:view>
</body>
</html>
When I run the App in the debugger, the value set correctly to the selectedProduct attribute, but then it's not accessible in the page - the output of product.xhtml looks following (if the chosen product has ID 4):
The value of shoppingCart.selectedProduct is:
Products on the main page are loaded from RequestScoped bean's (productController) property. The ShoppingCart is then a SessionScoped bean with injected productController instance.
package main.java;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import java.io.Serializable;
import java.util.List;
#Named
#SessionScoped
public class ShoppingCart implements Serializable {
private List<Product> selectedProducts;
private int numberOfSelectedProducts;
private Product selectedProduct;
public Product getSelectedProduct() {
return selectedProduct;
}
public void setSelectedProduct(Product selectedProduct) {
this.selectedProduct = selectedProduct;
}
public List<Product> getSelectedProducts() {
return selectedProducts;
}
public void setSelectedProducts(List<Product> selectedProducts) {
this.selectedProducts = selectedProducts;
}
public int getNumberOfSelectedProducts() {
return numberOfSelectedProducts;
}
public void setNumberOfSelectedProducts(int numberOfSelectedProducts) {
this.numberOfSelectedProducts = numberOfSelectedProducts;
}
}
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
#ViewScoped
#Named
public class ProductController implements Serializable {
private List<Product> products;
#Inject
private ShoppingCart shoppingCart;
public void setProducts(List<Product> products) {
this.products = products;
}
public ShoppingCart getShoppingCart() {
return shoppingCart;
}
public void setShoppingCart(ShoppingCart shoppingCart) {
this.shoppingCart = shoppingCart;
}
public List<Product> getProducts() {
return products;
}
//v teto metode se pote budou nacitat produkty z DB
#PostConstruct
public void loadItems(){
products = new ArrayList<>();
products.add(new Product(1, "Nazev1", 11, "Popis1"));
products.add(new Product(2, "Nazev2", 22, "Popis2"));
products.add(new Product(3, "Nazev3", 33, "Popis3"));
products.add(new Product(4, "Nazev4", 44, "Popis4"));
products.add(new Product(5, "Nazev5", 55, "Popis5"));
products.add(new Product(6, "Nazev6", 66, "Popis6"));
products.add(new Product(7, "Nazev7", 77, "Popis7"));
}
public Product findById(final int id) {
List<Product> product = products.stream().filter(p -> p.getId() == id).limit(1).collect(Collectors.toList());
return product.get(0);
}
}
package main.java;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.io.Serializable;
#Named
#ViewScoped
public class Product implements Serializable {
private int id;
private String name;
private double price;
private String description;
public Product(int id, String name, double price, String description) {
this.id = id;
this.name = name;
this.price = price;
this.description = description;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#PostConstruct
public void init(){
System.out.println("Product created");
}
}

If you add a #PostConstruct method to your #SessionScoped bean like this:
#PostConstruct
public void init() {
System.out.println("ShoppingCart.init()");
}
You will notice that your bean is instantiated several times per request - at least one time for each #{shoppengCart...} expression. This is because using the deprecated annotation #javax.faces.bean.SessionScoped within CDI environment behaves like #NoneScoped.
You should instead use javax.enterprise.context.SessionScoped for your shopping cart.
For display of a selected product I would suggest to add a #ViewScoped bean (javax.faces.view.ViewScoped, not javax.faces.bean.ViewScoped) or even #RequestScope if you don't do AJAX stuff. (javax.enterprise.context.RequestScoped, not javax.faces.bean.RequestScoped).
Which IDE do you use - didn't it notify you that the sope used by you is deprecated?
For further reading see: How to choose the right bean scope?
In addition to the scope problem, you should probably use f:viewParam instead of f:event to inject the URL query parameter into the bean:
Instead of:
<f:metadata>
<f:event type="preRenderView" listener="#{shoppingCart.loadSelectedProduct(param.id)}"/>
</f:metadata>
do this:
<f:metadata>
<f:viewParam name="id" value="#{productDisplayBean.selectedProductId}"/>
</f:metadata>

Related

PrimeFaces DataTables not working

I'm new to PrimeFaces tried out an example in PrimeFaces datatable
public class Datatable {
private String fname;
private String lname;
private int age;
public Datatable(String fname, String lname, int age) {
// TODO Auto-generated constructor stub
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Here in the class I have declared what are the fields in the data table
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean(name="solodat")
#RequestScoped
public class Solodata implements Serializable{
private static final long serialVersionUID = 1L;
public Solodata() {}
private List<Datatable>addeta;
public List<Datatable> getAddeta() {
return addeta;
}
public void setAddeta(List<Datatable> addeta) {
this.addeta = addeta;
}
#PostConstruct
public void init() {
List<Datatable> addeta=new ArrayList<Datatable>();
addeta.add( new Datatable("man","eater",14));
addeta.add( new Datatable("solo","world",28));
addeta.add( new Datatable("antan","evanious",20));
addeta.add( new Datatable("hi","daa",29));
addeta.add( new Datatable("thallu","vandi",30));
addeta.add( new Datatable("prime","faces",1000));
addeta.add( new Datatable("crime","shit",1412));
addeta.add( new Datatable("shit","head",18));
}
}
Here in list I have get that values:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://www.java.com/jsf/html"
xmlns:f="http://www.java.com/jsf/core"
xmlns:p="http://www.primefaces.org/ui">
<h:head>
<title>DATA TABLES DEMO</title>
</h:head>
<h:body>
<h:form>
<h1>output values</h1>
<p:dataTable var="sol" value="#{solodat.addeta}" >
<p:column headerText="LASTNAME">
<h:outputText value="#{sol.lname}"/>
</p:column>
<p:column headerText="age">
<h:outputText value="#{sol.age}"/>
</p:column>
<p:column headerText="first">
<h:outputText value="#{sol.fname}"/>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
This is the xhtml page to get the bean values by data table but JSF is showing an empty page. Any help would be appreciated.
Try this and let us know (using CDI, removing the useless constructor, and initializing addeta properly)
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
#Named("solodat")
#RequestScoped
public class Solodata {
private List<Datatable> addeta;
public List<Datatable> getAddeta() {
return addeta;
}
public void setAddeta(List<Datatable> addeta) {
this.addeta = addeta;
}
#PostConstruct
public void init() {
addeta=new ArrayList<Datatable>();
addeta.add( new Datatable("man","eater",14));
addeta.add( new Datatable("solo","world",28));
addeta.add( new Datatable("antan","evanious",20));
addeta.add( new Datatable("hi","daa",29));
addeta.add( new Datatable("thallu","vandi",30));
addeta.add( new Datatable("prime","faces",1000));
addeta.add( new Datatable("crime","shit",1412));
addeta.add( new Datatable("shit","head",18));
}
}
And replace the facelet with this one (I changed the first lines)
<!DOCTYPE html>
<html lang="en"
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">
<h:head>
<title>DATA TABLES DEMO</title>
</h:head>
<h:body>
<h:form>
<h1>output values</h1>
<p:dataTable var="sol" value="#{solodat.addeta}" >
<p:column headerText="LASTNAME">
<h:outputText value="#{sol.lname}"/>
</p:column>
<p:column headerText="age">
<h:outputText value="#{sol.age}"/>
</p:column>
<p:column headerText="first">
<h:outputText value="#{sol.fname}"/>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
Now make sure you have placed Primefaces library at the right place, and that the app is being deployed on a running server without errors.
Edit: The reason you don't have data , is due to Datatable's constructor, which is incomplete.
Replace
public Datatable(String fname, String lname, int age) {
// TODO Auto-generated constructor stub
}
by
public Datatable(String fname, String lname, int age) {
this.fname = fname;
this.lname = lname;
this.age = age;
}
Small mistake: You are initializing a new local variable in init().
List<Datatable> addeta = new ArrayList<Datatable>();
Change it to:
this.addeta = new ArrayList<Datatable>();
You should use <!DOCTYPE html> instead of
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
and also change your are initializing as noone answer.
See also : Wrong doctype when one is specified in composite view

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.

Datatable 7 items on each row

Let's say I have a list of all the days in a month and I want to print it as a calendar. I want a week on each line and then a row break
in my example below, I will get a day on each row, like this:
Which is the best way to get 7 days on each row like this in JSF?
Example code:
View:
<h:dataTable value="#{myController.dayList}" var="day">
<h:column>
<h:outputText value="#{day}"/>
</h:column>
</h:dataTable>
Backbean:
#ManagedBean(name = "myController")
#SessionScoped
public class MyController {
private List <int> dayList;
public MyController()
{
dayList = getAllDaysInMonth();
}
public List <int> getAllDaysInMonth()
{
.....
}
public List <int> getDayList()
{
return dayList;
}
public void setDayList(List <int> dayList)
{
this.dayList = dayList;
}
}
if you would like to use Primefaces in your Project, you could do it in this way.
<!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:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<body>
<p:dataGrid value="#{myController.dayList}" var="day" columns="7">
<p:panel style="text-align: center; background-color: skyblue; width: 100px; height: 100px;">
Day ${day}
</p:panel>
</p:dataGrid>
</body>
</html>
The Controller class
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named(value = "myController")
#SessionScoped
public class MyController implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
List<Integer> dayList = new ArrayList<>();
public MyController() {
}
#PostConstruct
public void init() {
for(int i = 1; i <= 31; i++) {
dayList.add(new Integer(i));
}
}
public List<Integer> getDayList() {
return dayList;
}
public void setDayList(List<Integer> dayList) {
this.dayList = dayList;
}
}
Looks not very nice, but does what you need.
Patrick

JSF and EJB integration

I am trying to create a login page for my application but i am stuck on the very first step. My form is working fine before using session facade in my bean, after adding session facade i got property not found exception:
My page is:
<!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">
<f:view contentType="text/html">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
<title>PrimeFaces</title>
</f:facet>
</h:head>
<h:body>
<h:form>
<p:panelGrid columns="2">
<p:outputLabel value ="Username"/> <p:inputText id="userName" value="#{loginBean.user}"/>
<p:outputLabel value ="Password"/> <p:inputText id="password" value="#{loginBean.password}"/>
</p:panelGrid>
<p:commandButton value="Login" actionListener="#{loginBean.doLogin}"/>
</h:form>
</h:body>
</f:view>
</html>
Working Bean Code is :
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package Beans;
import entities.Program;
import entities.ProgramFacade;
import entities.ProgramFacadeLocal;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import javax.annotation.ManagedBean;
import javax.ejb.EJB;
import javax.faces.event.ActionEvent;
/**
*
* #author Salman Ahmed Ansari
*/
#Named(value = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
/**
* Creates a new instance of LoginBean
*/
private String user;
private String password;
public String getUser() {
return user;
}
public String getPassword() {
return password;
}
public void setUser(String user) {
this.user = user;
}
public void setPassword(String password) {
this.password = password;
}
public void doLogin(ActionEvent listener){
System.out.println(user);
System.out.println(password);
}
public LoginBean() {
}
}
and not working bean code is :
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package Beans;
import entities.Program;
import entities.ProgramFacade;
import entities.ProgramFacadeLocal;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import javax.annotation.ManagedBean;
import javax.ejb.EJB;
import javax.faces.event.ActionEvent;
/**
*
* #author Salman Ahmed Ansari
*/
#Named(value = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
#EJB
private ProgramFacade programFacade;
/**
* Creates a new instance of LoginBean
*/
private String user;
private String password;
public String getUser() {
return user;
}
public String getPassword() {
return password;
}
public void setUser(String user) {
this.user = user;
}
public void setPassword(String password) {
this.password = password;
}
public void doLogin(ActionEvent listener){
System.out.println(user);
System.out.println(password);
}
public LoginBean() {
}
}
What triggers this exception?
Thanks in Advance ..

Inserting element in an arraylist to render empty line

I am using primefaces on the frontend and populating a selectOneList using an arraylist in my backing bean
I want to have the array list separated by new lines to make some logical separations
How can I add an element to an ArrayList that will be rendered as an empty line ?
The following code will help you to achieve the functionality you want, that is to enter some empty line in <p:selectOneListBox>. Now I am not sure if it is a feature of this component that to squeeze out the empty string. So "" will not work.
This is a sample managed bean:
package app.so.dev.web.controller;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import app.so.dev.web.model.Student;
#ManagedBean(name = "so15350373")
#ViewScoped
public class SO15350373 implements Serializable{
private static final long serialVersionUID = 2190171095461884759L;
private List<Student> students;
private int selected;
#PostConstruct
public void init() {
students = new ArrayList<Student>();
students.add(new Student(1, "Student 1"));
students.add(new Student(2, " "));
students.add(new Student(3, "Student 3"));
students.add(new Student(4, " "));
students.add(new Student(5, "Student 5"));
students.add(new Student(6, "Student 6"));
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public int getSelected() {
return selected;
}
public void setSelectedStudent(int selected) {
this.selected = selected;
}
}
The Student is a simple POJO having two field id and name. For the sake of brevity, I am not showing this class :P.
And this is the xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui" template="/WEB-INF/templates/globalTemplate.xhtml">
<ui:define name="title">15350373</ui:define>
<ui:define name="content">
<h:form>
<p:selectOneListbox value="#{so15350373.selected}" id="list">
<f:selectItems value="#{so15350373.students}" var="student" itemLabel="#{student.name}" itemValue="#{student.id}" />
</p:selectOneListbox>
</h:form>
</ui:define>
</ui:composition>

Resources