The reason why the topic has "kind of" is because I have an example in JSF 2.2 where I use a commandButton and call a bean function twice (depending on the url). It's basically the same code, which executes only in one example.
Here's the code with the description of the "error" below the code:
User bean
@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(){}
}
UsersBean bean:
@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));
listOfUsers.add(new User("Cercei", "Lannister", 29, 4));
listOfUsers.add(new User("John", "Snow", 31, 5));
}
public List<User> getAll() {
System.out.println("getAall is 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 String addUser(User u) {
System.out.println("addUser is called.");
if (u.getId() != 0) {
for (User edit : listOfUsers) {
if (edit.getId() == u.getId()) {
System.out.println("Found it!");
edit.setAge(u.getAge());
edit.setName(u.getName());
edit.setSurname(u.getSurname());
}
}
} else {
u.setId(listOfUsers.size() + 1);
listOfUsers.add(u);
}
return "";
}
}
users.xhtml:
<f:view>
<!-- https://mcmap.net/q/17679/-method-must-have-signature-quot-string-method-etc-quot-but-has-signature-quot-void-method-quot -->
<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="users" value="edit user">
<f:param name="userID" value="#{u.id}"></f:param>
<f:param name="action" value="edit"></f:param>
</h:link>
<h:link outcome="usersDetails" value="get details">
<f:param name="userID" value="#{u.id}"></f:param>
</h:link>
</h:column>
</h:dataTable>
<h:panelGroup rendered="#{param['action'] == 'edit'}">
<h1>Edit!</h1>
<h:form>
<ui:param name="editUser" value="#{usersBean.details}"></ui:param>
<h:outputText value="Name"></h:outputText>
<h:inputText value="#{editUser.name}"></h:inputText> <br />
<h:outputText value="Surname"></h:outputText>
<h:inputText value="#{editUser.surname}"></h:inputText> <br />
<h:outputText value="Age"></h:outputText>
<h:inputText value="#{editUser.age}"></h:inputText> <br />
<h:commandButton action="#{usersBean.addUser(editUser)}" value="Edit" type="submit"> </h:commandButton>
</h:form>
</h:panelGroup>
<h:panelGroup rendered="#{empty param['action']}">
<h1>Add!</h1>
<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>
</h:panelGroup>
</f:view>
OK, so, everything works perfectly. usersBean.addUser adds the user. If I add another inputText for ID and I put in an existing ID, the corresponding function updates the values. So, addUser function works as expected.
The problem is in case of
<h:panelGroup rendered="#{param['action'] == 'edit'}">
as you can see in the xhtml above, the code is basically the same, with the sole exception that I fill in the data of the user that was selected. This works, I get the appropriate data into input fields, but when I change them and click Edit, nothing happens. The function is not called! whereas in case of add, the function is called and it works. It appears as if there is no action defined in case of edit, it only reloads the page (submit) without the actual action addUser.
How is this caused and how can I solve it?