Getter gets called as many times as there are values in ArrayList for h:dataTable and Eclipse says "Method must have signature "String method ..." [duplicate] - eclipse

This question already has answers here:
Why JSF calls getters multiple times
(9 answers)
How and when should I load the model from database for JSF dataTable
(1 answer)
Method must have signature "String method() ...[etc]..." but has signature "void method()"
(1 answer)
Closed 3 years ago.
I'm really new to JSF, I've been learning it exactly 2 days now. Besides the initial confusion about the concepts, I have issues with eclipse too.
I'm using JSF 2.0 with obviously Eclipse and Tomcat 7.
Firstly, let me describe what I'd want to do: in scope of learning the JSF I want to have a User class, with name, surname, age and Id. Then, I'd like to list pre-defined users and add a submit form. Besides that, there's also a "user detail" option.
Here's my code:
User class:
package com.tutorial;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class User {
private String name;
private String surname;
private int age;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public User(String name, String surname, int age, int id) {
super();
this.name = name;
this.surname = surname;
this.age = age;
this.id = id;
}
public User(){}
}
Users "bean":
package com.tutorial;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
#ManagedBean
#SessionScoped
public class UsersBean {
private List<User> listOfUsers = new ArrayList<User>();
private String passedParameter;
public UsersBean()
{
listOfUsers.add(new User("Tywin", "Lannister", 60, 1));
listOfUsers.add(new User("Tyrion", "Lannister", 30, 2));
listOfUsers.add(new User("Jaime", "Lannister", 31, 3));
}
public List<User> getAll()
{
System.out.println("Called!");
return listOfUsers;
}
public User getDetails()
{
passedParameter = (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("userID");
int id = Integer.parseInt(passedParameter);
User selected = null;
for (User u : listOfUsers)
{
if (u.getId() == id)
{
selected = u;
}
}
return selected;
}
public void addUser(User u)
{
u.setId(listOfUsers.size()+1);
listOfUsers.add(u);
}
}
users.xml (partial code):
<f:view>
<!-- http://stackoverflow.com/questions/8083469/method-must-have-signature-string-method-etc-but-has-signature-void -->
<h:dataTable value="#{usersBean.all}" var="u">
<h:column>
<f:facet name="header">
User ID
</f:facet>
#{u.id}
</h:column>
<h:column>
<f:facet name="header">
Name
</f:facet>
#{u.name}
</h:column>
<h:column>
<f:facet name="header">
Details
</f:facet>
<h:link outcome="usersDetails" value="get details">
<f:param name="userID" value="#{u.id}"></f:param>
</h:link>
</h:column>
</h:dataTable>
<h:form>
<h:outputText value="Name"></h:outputText>
<h:inputText value="#{user.name}"></h:inputText>
<h:outputText value="Surname"></h:outputText>
<h:inputText value="#{user.surname}"></h:inputText>
<h:outputText value="Age"></h:outputText>
<h:inputText value="#{user.age}"></h:inputText>
<h:commandButton action="#{usersBean.addUser(user)}" value="Add" type="submit"></h:commandButton>
</h:form>
</f:view>
And finally, usersDetails.xhtml (partial code as well):
<ui:define name="content">
<ui:param name="user" value="#{usersBean.details}" />
<h:outputText value="#{user.name}"></h:outputText>
<h:outputText value="#{user.surname}"></h:outputText>
<h:outputText value="#{user.id}"></h:outputText>
</ui:define>
OK, now the questions:
(1) in users.xhtml (see code above - usersBean.all in datatable), it appears as if this function gets called as many times as there are values in arraylist. The "System.out.println("Called!")" is written as many times as there are values in arraylist. Have I done something wrong? I don't believe it's suppose to be called for each object in arraylist.
(2) in users.xhtml, this part of the code
<h:commandButton action="#{usersBean.addUser(user)}" value="Add" type="submit"></h:commandButton>
is highlighted by eclipse and it reads: "Method must have signature "String method(),..."
Did I call the method the wrong way? Is there an alternative to send object to the UsersBean's addUser function? What would be correct way if Eclipse defines this as wrong?
Thank you very much for your time and answers!

1) In JSF, method (used for bulding view) can be called more than once. For proper testing you can create user list with 20 or more users and check again how many times getAll method will be called. I think it still be the same number (3 in your case).
2) Action method in JSF should return redirection outcome (with type String). It is reason why you have message about "signature String method". Change signature of addUser method from public void addUser(User u) to public String addUser(User u) and return outcome for navigation to new page or null for stay on the same page.

Related

How can I create h:selectOneRadio with options of a java list (JSF)? [duplicate]

This question already has answers here:
How to populate options of h:selectOneMenu from database?
(5 answers)
Closed 6 years ago.
I would like a JSF menu with h:selectOneRadio and information of Java ArrayList.
This is my code:
XHTML:
<h:selectOneRadio value="#{bean.element}">
<ui:repeat value = "#{bean.items}" var = "i">
<f:selectItem itemValue="#{bean.elements[i]}" itemLabel="#{bean.elements[i]}" />
</ui:repeat>
</h:selectOneRadio>
Bean:
package bean.controlador;
import java.io.IOException;
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
#ManagedBean
#SessionScoped
public class Bean {
private String element;
private ArrayList<Integer> items;
private ArrayList<String> elements;
public Bean() {
element = "hello";
elements = new ArrayList<String>();
elements.add("world");
elements.add("hello");
elements.add("thanks");
items = new ArrayList<Integer>();
items.add(1);
items.add(2);
items.add(3);
}
public void load() throws IOException {
FacesContext.getCurrentInstance().getExternalContext().redirect("link.xhtml");
}
public void listenerFuncion() {
System.out.println("Listener");
}
public String getElement() {
return element;
}
public void setElement(String element) {
this.element = element;
}
public ArrayList<Integer> getItems() {
return items;
}
public void setItems(ArrayList<Integer> items) {
this.items = items;
}
public ArrayList<String> getElements() {
return elements;
}
public void setElements(ArrayList<String> elements) {
this.elements = elements;
}
}
The XHTML is empty, I don't see any item. I would like load all list and with a click on any selectItem, the element variable change its value.
Thank you!
Instead of using a ui:repeat and f:selectItem, use f:selectItems, which can take a list of items.
Here is an example for your situation:
<h:selectOneRadio value="#{bean.element}">
<f:selectItems value="#{bean.items}" var="i" itemValue="#{bean.elements[i]}" itemLabel="#{bean.elements[i]}" />
</h:selectOneRadio>
I'm not sure I fully understand the contents of the variables you are using, but this may also work better for you:
<h:selectOneRadio value="#{bean.element}">
<f:selectItems value="#{bean.elements}" var="i" itemValue="#{i}" itemLabel="#{i}" />
</h:selectOneRadio>

Can not get data table row selection in PrimeFaces, jsf?

I'm working on a project. I need to get a list from MySql database and list it. I'm using JSF 2.1 Primeface 3.5 and Eclipse Juno. I run my code but it doesn't work. You can see my codes in below
//LOGIN CLASS
import parts
#ManagedBean
#SessionScoped
public class Login {
private String username, password;
private PreparedStatement ps, ps2;
private ResultSet rs, rs2;
private List<Application> applications = new ArrayList<Application>();;
private Application selectedApplication;
// GETTERS SETTERS
public String login() {
Connection object = new Connection();
try {
ps = nesne
.getCon()
.prepareStatement(
"select Username, Password from company where Username=? and Password=?");
ps.setString(1, getUsername());
ps.setString(2, getPassword());
rs = ps.executeQuery();
while (rs.next()) {
getList();
return "application";
}
} catch (Exception e) {
System.err.println(e);
}
return "confirm";
}
private List<Application> getList() {
Baglanti nesne = new Baglanti();
try {
ps2 = nesne
.getCon()
.prepareStatement(
"select ApplicationName from application where CompanyID=(select ID from company "
+ "where Username=? and Password=?)");
ps2.setString(1, getUsername());
ps2.setString(2, getPassword());
rs2 = ps2.executeQuery();
while (rs2.next()) {
Application obj = new Application();
obj.setApplicationName(rs2.getString("ApplicationName"));
applications.add(obj);
}
} catch (Exception e) {
System.err.println(e);
}
return applications;
}
APPLICATION CLASS
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class Application {
private int ID;
private int CompanyID;
private String Type;
private Date Date;
private String ApplicationName;
private int CurrentMessageCount;
private int MaxMessage;
private String isPro;
//GETTERS SETTERS
application.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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Login Confirmed</title>
</h:head>
<h:body>
<h1 class="ui-widget-header ui-corner-all" align="center">Application
List</h1>
<br />
<h:form id="form">
<p:growl id="msgs" showDetail="true" />
<p:dataTable id="applications" var="application"
value="#{login.applications}">
<p:column headerText="Application" style="width:24%">
<h:outputText value="#{login.applications}" />
</p:column>
<p:column style="width:4%">
<p:commandButton id="selectButton" icon="ui-icon-search"
title="View">
<f:setPropertyActionListener value="#{application}"
target="#{login.selectedApplication}" />
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
I can login properly after that ı saw this page.
Now where is my mistake?
Your var="application" is conflicting with the implicit EL object referring the application context (the ServletContext). You can find here a list of all implicit EL objects. Memorize them. You should never declare an EL variable on exactly those names.
Give it a different name. E.g. var="app", var="_application", etc.
In data table var property mean that every item from database will be accesible as this "var" value. i.e:
You have class Foo:
class Foo{
int number;
String text;
//Setters and getters
}
And another class which handle list of Foo objects (your model as CDI Bean):
#Named
class Boo{
List<Foo> list = new ArrayList<>();
//Getter and setters
}
So to list it all in jsf page you should use it like this:
<p:dataTable id="list" var="listobject" value="#{boo.list}">
<p:column headerText="Number" style="width:24%">
<h:outputText value="#{listobject.number}" />
</p:column>
<p:column headerText="Text" style="width:24%">
<h:outputText value="#{listobject.String}" />
</p:column>
</p:dataTable>
So summary "var" value is accessor string to boo object.
Look also:
PrimeFaces datatable demo and here
Mkyong datatable tutorial

JSF view displaying outdated value

I have two entities and a backing bean in my application. Following, a simplified version of it:
Controller and Models:
class BackingBean {
private List<A> collectionOfA;
private A currentA;
private B currentB;
private String newDescription;
// accessors
public void prepareForUpdate(ActionEvent e) {
currentA = (A) e.getComponent().getAttributes().get("a");
currentB = (B) e.getComponent().getAttributes().get("b");
}
public void save(ActionEvent e) {
// method to save b
b.setName("changing the name");
b.setSomeNumber(2);
b.setDescription(newDescription);
entityManager.merge(b);
}
}
#Entity
class A {
private String name;
#OneToMany
private List<B> bs;
}
#Entity
class B {
private String name;
private String description;
private int someNumber;
}
View:
<div>
<!-- some popup with inputs for updating B -->
<h:inputText value="#{backingBean.currentB}" />
<h:commandLink actionListener="#{backingBean.save}" />
</div>
<ui:repeat value="#{backingBean.collectionOfA}" var="a">
<h:outputText>#{a.name}</h:outputText>
<ui:repeat value="#{a.bs}" var="b">
#{b.name}
#{b.description}
#{b.someNumber}
<h:commandLink actionListener="#{backingBean.prepareForUpdate}">
<f:attribute name="a" value="#{a}" />
<f:attribute name="b" value="#{b}" />
</h:commandLink>
</ui:repeat>
</ui:repeat>
Assuming that, when I click the commandLink for prepareForUpdate(), the popup shows, my problem is this: when I save the currentB entity, every field of the entity is updated in the view. However, an instant after, the field b.description is rendered again with the old value. When I check the database, the description is, in fact, updated, as it is if I refresh the page.
Any thoughts on why this is happening?

Avoiding entity update directly on form submit

I have an entity which is showed on the screen as text in input boxes which can be modified. When i submit the form hitting save, i would like my ejb3 component to handle the data and persist or merge it using the entity manager. But for some reason, when i modify the data and hit save the data directly gets updated in the database by-pasing my ejb3, which is certainly undesirable. My code looks like the following
#Entity
#Table(name = "EMP")
public class Emp implements java.io.Serializable {
private short empno;
private Dept dept;
private String ename;
private String job;
private Short mgr;
private Date hiredate;
private BigDecimal sal;
private BigDecimal comm;
public Emp() {
}
public Emp(short empno) {
this.empno = empno;
}
public Emp(short empno, Dept dept, String ename, String job, Short mgr,
Date hiredate, BigDecimal sal, BigDecimal comm) {
this.empno = empno;
this.dept = dept;
this.ename = ename;
this.job = job;
this.mgr = mgr;
this.hiredate = hiredate;
this.sal = sal;
this.comm = comm;
}
#Id
#Column(name = "EMPNO", unique = true, nullable = false, precision = 4, scale = 0)
public short getEmpno() {
return this.empno;
}
public void setEmpno(short empno) {
this.empno = empno;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "DEPTNO")
public Dept getDept() {
return this.dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
#Column(name = "ENAME", length = 10)
#Length(max = 10)
public String getEname() {
return this.ename;
}
public void setEname(String ename) {
this.ename = ename;
}
#Column(name = "JOB", length = 9)
#Length(max = 9)
public String getJob() {
return this.job;
}
public void setJob(String job) {
this.job = job;
}
#Column(name = "MGR", precision = 4, scale = 0)
public Short getMgr() {
return this.mgr;
}
public void setMgr(Short mgr) {
this.mgr = mgr;
}
#Temporal(TemporalType.DATE)
#Column(name = "HIREDATE", length = 7)
public Date getHiredate() {
return this.hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
#Column(name = "SAL", precision = 7)
public BigDecimal getSal() {
return this.sal;
}
public void setSal(BigDecimal sal) {
this.sal = sal;
}
#Column(name = "COMM", precision = 7)
public BigDecimal getComm() {
return this.comm;
}
public void setComm(BigDecimal comm) {
this.comm = comm;
}
}
#Stateful
#Name("workflow")
#Scope(ScopeType.CONVERSATION)
public class WorkflowBean implements Workflow
{
#Logger private Log log;
#In StatusMessages statusMessages;
#PersistenceContext(type=PersistenceContextType.EXTENDED)
EntityManager entityManager;
#Out(required=false)
Emp employee = new Emp();
#RequestParameter("empEmpno")
String empNo;
public void workflow()
{
log.info("workflow.workflow() action called");
statusMessages.add("workflow");
}
#End
public boolean save(){
entityManager.merge(emp);
entityManger.flush();
}
#Begin(join=true)
public boolean populateEmp(){
entityManager.setFlushMode(FlushModeType.COMMIT);
System.out.println("The Emp No. is---"+empNo);
int no = Integer.parseInt(empNo);
short emp =(short)no;
employee = entityManager.find(Emp.class, emp);
entityManager.flush();
return true;
}
public Emp getEmployee() {
return employee;
}
public void setEmployee(Emp employee) {
this.employee = employee;
}
// add additional action methods
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
#Remove
#Destroy
public void destroy() {
}
}
My view looks like
<h:form id="emp" styleClass="edit">
<rich:panel>
<f:facet name="header">Edit Emp</f:facet>
<s:decorate id="empnoField" template="layout/edit.xhtml">
<ui:define name="label">Empno</ui:define>
<h:inputText id="empno"
required="true"
value="#{workflow.employee.empno}">
</h:inputText>
</s:decorate>
<s:decorate id="commField" template="layout/edit.xhtml">
<ui:define name="label">Comm</ui:define>
<h:inputText id="comm"
value="#{workflow.employee.comm}"
size="14">
</h:inputText>
</s:decorate>
<s:decorate id="enameField" template="layout/edit.xhtml">
<ui:define name="label">Ename</ui:define>
<h:inputText id="ename"
size="10"
maxlength="10"
value="#{workflow.employee.ename}">
</h:inputText>
</s:decorate>
<s:decorate id="hiredateField" template="layout/edit.xhtml">
<ui:define name="label">Hiredate</ui:define>
<rich:calendar id="hiredate"
value="#{workflow.employee.hiredate}" datePattern="MM/dd/yyyy" />
</s:decorate>
<s:decorate id="jobField" template="layout/edit.xhtml">
<ui:define name="label">Job</ui:define>
<h:inputText id="job"
size="9"
maxlength="9"
value="#{workflow.employee.job}">
</h:inputText>
</s:decorate>
<s:decorate id="mgrField" template="layout/edit.xhtml">
<ui:define name="label">Mgr</ui:define>
<h:inputText id="mgr"
value="#{workflow.employee.mgr}">
</h:inputText>
</s:decorate>
<s:decorate id="salField" template="layout/edit.xhtml">
<ui:define name="label">Sal</ui:define>
<h:inputText id="sal"
value="#{workflow.employee.sal}"
size="14">
</h:inputText>
</s:decorate>
<s:decorate id="deptField" template="layout/edit.xhtml">
<ui:define name="label">Department</ui:define>
<h:inputText id="dname"
value="#{workflow.deptName}">
</h:inputText>
</s:decorate>
<div style="clear:both">
<span class="required">*</span>
required fields
</div>
</rich:panel>
<div class="actionButtons">
<h:commandButton id="save"
value="Save"
action="#{workflow.save}"
rendered="true"/>
</div>
</h:form>
[It was difficult to address issue in comments for your response.]
There are few things which I haven't understand & why it's done that way.
Using transient fields, it will add overhead of adding those to entity object while persisting.
Why is auto-commit causes issue & can't be implemented.
Regardless of these things, you can try
Making the entity detached with entityManager.detach(entity) or clearing the persistence context with entityManager.clear(), detaching all the underlying entities. But prior one is more favourible.
Can manage transaction manually instead of container. Use BMT where you can have control over the operations.

What is a form based application?

What does it mean that an application is "form based"? I am reading the JSF specification and term turned up.
Form based application, means that for each form, there is a backend bean (java class) that handles the calls to the class.
For instance, you will have a form for login (login.xhtml) and you will present all getter and setters of the values that are needed in the form, in LoginBean.java
All operations (like retrieving data from db) only for this form, will be done in a postconstruct method.
So if login has username and password like this:
<h:inputtext name="name" value="#{loginBean.name}" />
<h:inputtext name="password" value="#{loginBean.password}" />
The LoginBean.java will look:
public class LoginBean{
String name;
String password;
public getName(){return name;}
public getPassword(){return password;}
public setName(String name){
this.name = name;
}
public setPassword(String password){
this.password = password;
}
#PostContruct
public void init(){
this.name = ... //get the name from db
}
}