I've been struggling with a task that seemed to be very simple, but somehow I can't see a way to solve it without using some pretty hacky code - which I really want to avoid.
The problem itself has been reduced to a very simple task: I have a project with a single page containing a form, where I have to type a non-empty username and use a select element (h:selectOneMenu) to choose one "user group" for this user. This is submitted to a RequestScoped bean that I have (this is also the only bean I have in the project). Only validation rule (to simplify my explanation) is: the "username" field cannot be empty.
Here's my page's code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://xmlns.jcp.org/jsf/passthrough">
<h:head></h:head>
<h:body>
<f:metadata>
<f:event listener="#{userManagementBean.initializeGroupsList()}" type="preRenderView" />
</f:metadata>
<h:form>
<h:inputText id="fieldUsername" value="#{userManagementBean.user.username}" p:placeholder="Username" required="true" />
<h:message for="fieldUsername"/>
<h:selectOneMenu id="fieldGroup" value="#{userManagementBean.usergroup_id}">
<f:selectItem itemValue="#{null}" itemLabel="Please, select a group" />
<f:selectItems value="#{userManagementBean.groupsList}" var="curGroup" itemLabel="#{curGroup.groupName}" itemValue="#{curGroup.id}" />
</h:selectOneMenu>
<h:message for="fieldGroup"/>
<h:commandButton action="#{userManagementBean.submitValues()}" value="Submit data" />
</h:form>
</h:body>
</html>
And here's the bean's code, which initializes a list containing the elements of the select box:
import java.io.Serializable;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
....
@RequestScoped
@Named
public class UserManagementBean implements Serializable {
// PRIVATE FIELDS
private User user = new User();
private List<UserGroup> groupsList;
private Integer usergroup_id;
// BEAN'S PUBLIC METHODS
public void initializeGroupsList() {
groupsList = loadAllGroupsFromDatabase();
System.out.print(String.format("%d groups have been loaded\n", groupsList.size()));
}
// Getters, setters and database-loading code has been ommited
...
}
Question is: when/how should I initialize the list of user groups, which is used to populate the select element on the page?
First I tried to use an <f:event> element which calls initializeGroupsList() on the "preRenderView" event (as in the code I've wrote above). Everything is populated fine, but if I select a user group and do not type any username, the select element returns an error message after the form is submitted ("Validation Error: Value is not valid"), while it should not give me any validation errors, as the user has selected a valid user group.
Secondly, I have tried replacing the <f:event> by a <f:viewAction> which calls initializeGroupsList(). When I open the page for the first time, everything works fine. But when I submit the form without a username, the page is reloaded, showing me the validation error, and the select element is not populated with any user groups at all (the initializeGroupsList() isn't called at all when there are validation errors in this case).
Currently I'm solving this issue by removing both the <f:event> and <f:viewAction> elements, and annotationg initializeGroupsList() with @PostConstruct. Problem is: if I do so, I won't be abble to access any of the URL's query string parameters through the use of <f:viewParam> inside the initializeGroupsList(), which is something I want to be able to do in this page in a near future.
How should I call initializeGroupsList() then, to avoid these errors described in both the first and second cases, while allowing me to access URL's query string parameters inside initializeGroupsList()?
Thanks in advance.