0
votes

I have a managed bean called User which has a String property called name:

public class User {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

I have another managed bean called UserManager which has a property of type User and allows you to add a user to a user list:

public class UserManager {
    private List<User> userList = new ArrayList<User>();
    private User user;
    public User getUser() {
        return this.user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public String addUser() {
        userList.add(user);
        return "_USERADDED";
    }
}

My JSF page to add the user looks like the following:

<h:form>
    <h:inputText value="#{userManager.user.name}"/>
    <h:commandButton value="Add User" action="#{userManager.addUser}"/>
</h:form>

The problem I am having is when I run my page and click the "Add User" button I get the following error:

adduser.xhtml @11,50 value="#{userManager.user.name}": Target Unreachable, 'null' returned null

I am assuming this error is due to the fact that the user property in UserManager is null and I am trying to access it to set the property name.

I can get this to work if I modify UserManager and initialize the user property:

private User user = new User();

My question is, is this the correct way to initialize the property or can I do it from within the JSF file and/or a config file?

1
In first place, it would be good to add the scope of your managed beans: @RequestScoped, @ViewScoped, etc. In second place, you can't just add a reference from a managed bean to another, they're classes but you don't manage their creation, the JSF container will. The best option will be to first define your entities and then use them in your managed beans. Rule of thumb: business entity != JSF (or CDI) managed bean.Luiggi Mendoza

1 Answers

3
votes

Yes, you're supposed to create it yourself. JSF/EL won't autocreate nested properties. Canonical approach is to use the @PostConstruct for this.

@ManagedBean
@RequestScoped
public class UserManager {

    private List<User> userList = new ArrayList<User>();
    private User user;

    @PostConstruct
    public void init() { 
        user = new User();
    }

    public String addUser() {
        userList.add(user);
        return "_USERADDED";
    }

    public User getUser() {
        return user;
    }

}

Note that I omitted the setter as it's never used by JSF/EL. I still wonder what userList is doing there, it doesn't belong there. I'll assume that it's just a stub for testing. In that case, it'd probably better be an application or session scoped bean which you inject by @ManagedProperty.