I tried to change it to ViewScoped but then its ending up with "calling the constructor" for the bean everytime i access a property...
Meanwhile i tried a lot of things, nothing worked as expected:
The ONLY case where i can get it to work is setting the Controllers to "SessionScoped". But i don't think this is a good approach since i would need to take care of "cleaning" values and cause a lot of unneded (initialized) beans...
I've created a simple Project to play arround. Heres the Session Scoped Version that is working. But if i change the scope, i would need to "reload" the current user when hitting the save button. And without access to request parameters i have no clue, how to achieve that.
(i tried passing the users id again with the "form", but then i have problems to pass the id "for the first time")
Heres my sample. (Getter and Setter are available and not mentioned to keep it short)
User-Class:
public class User { private String firstname; private String lastname; public User (String f, String l){ this.firstname = f; this.lastname = l; } }
DBSimulator:
@Named("dbSimulator") @SessionScoped public class DBSimulator implements Serializable { /** * */ private static final long serialVersionUID = 659826879566280911L; private Map<String, User> data; public DBSimulator() { //Load data User u1 = new User("Mickey", "Maus"); User u2 = new User("Peter", "Pan"); this.data = new HashMap<String, User>(); this.data.put("Mickey", u2); this.data.put("Max", u1); } public List<User> getUserList(){ List<User> l = new LinkedList<User>(); for (Map.Entry<String, User> user : data.entrySet()) { l.add(user.getValue()); } return l; } public void saveUser(User user){ this.data.put(user.getFirstname(), user); } }
UserManagement-Controller:
@Named @SessionScoped public class UserManagementController implements Serializable { /** * */ private static final long serialVersionUID = -4300851229329827994L; @Inject private DBSimulator dbSimulator; private List<User> users; public UserManagementController() { System.out.println("UserManagementController:construct()"); } @PostConstruct public void LoadUsers(){ this.setUsers(this.dbSimulator.getUserList()); } }
UserEdit Controller
@Named @SessionScoped public class UserEditController implements Serializable{ /** * */ private static final long serialVersionUID = 1867483972880755108L; @Inject private DBSimulator dbSimulator; private User user; public UserEditController() { System.out.println("UserEditController:construct()"); } public String activateUser(User user){ this.setUser(user); System.out.println("setting User"); return "userEdit"; } public String save(){ //Save user this.dbSimulator.saveUser(user); return "userManagement"; } }
and finaly both XHTML files: UserManagement.xhtml
<!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://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core"> <h:head> <title>Test</title> </h:head> <h:body> <h:outputText value="Select user to edit." /> <h:dataTable value="#{userManagementController.users}" var="user"> <h:column> <f:facet name="header">Firstname</f:facet> <h:outputText value="#{user.firstname}" /> </h:column> <h:column> <f:facet name="header">Lastname</f:facet> <h:outputText value="#{user.lastname}" /> </h:column> <h:column> <f:facet name="header">Options</f:facet> <h:form> <h:commandLink action="userEdit" actionListener="#{userEditController.activateUser(user)}" value="edit user" /> </h:form> </h:column> </h:dataTable> </h:body> </html>
UserEdit.xhtml
<!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://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core"> <h:head> <title>Test</title> </h:head> <h:body> <h:form> <h:inputText value="#{userEditController.user.firstname}"></h:inputText> <br /><br /> <h:inputText value="#{userEditController.user.lastname}"></h:inputText> <br /><br /> <h:commandButton value="save" action="#{userEditController.save}"></h:commandButton> </h:form> </h:body> </html>
ps.: I don't want anyone to "correct" my code - but maybe with the complete example somebody is able to see, where my headeck comes from :)
Working with ViewScoped Beans generates the following console Output:
[pageload] 12:07:49,126 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:07:49,334 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:07:49,341 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() [edit click] 12:08:35,410 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,411 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,412 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,413 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,414 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,414 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,415 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,416 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,416 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,417 INFO [stdout] (http--0.0.0.0-8090-3) UserManagementController:construct() 12:08:35,476 INFO [stdout] (http--0.0.0.0-8090-3) UserEditController:construct() 12:08:35,478 INFO [stdout] (http--0.0.0.0-8090-3) setting User 12:08:35,494 INFO [stdout] (http--0.0.0.0-8090-3) UserEditController:construct() 12:08:35,497 INFO [stdout] (http--0.0.0.0-8090-3) UserEditController:construct()
And obviously the user is not set anymore, because the (ViewScoped) UserEditController has been reconstructed twice after setting the user...