I think that the question is simple, I get the error:
Caused by: java.lang.NullPointerException
at co.edu.unal.bienestar.dao.UserDao.save(UserDao.java:27)
at co.edu.unal.bienestar.facade.UserFacade.createUser(UserFacade.java:18)
at co.edu.unal.bienestar.mb.UserMB.createUser(UserMB.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
... 27 more
When I try the create a new user, with a application which only have a entity class:
@Entity
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String username;
private String password;
private Role role;
<here getters and setters>
}
a Data Access Object:
public class UserDao {
@PersistenceContext
private EntityManager em;
public void save(User user) {
em.persist(user);
}
public void delete(User user) {
User userToBeRemoved = em.merge(user);
em.remove(userToBeRemoved);
}
public User update(User user) {
return em.merge(user);
}
public List<User> findAll() {
TypedQuery<User> query = em.createQuery(
"SELECT u FROM User u ORDER BY u.id", User.class);
return query.getResultList();
}
}
a facade:
public class UserFacade {
private UserDao userDao = new UserDao();
public void createUser(User user) {
userDao.save(user);
}
public List<User> listAll() {
List<User> result = userDao.findAll();
return result;
}
}
User Managed Bean:
@SessionScoped
@ManagedBean(name = "userMB")
public class UserMB implements Serializable {
public static final String INJECTION_NAME = "#{userMB}";
private static final long serialVersionUID = 1L;
private User user;
private UserFacade userfacade;
public User getUser() {
if (user == null) {
user = new User();
}
return user;
}
public void setUser(User user) {
this.user = user;
}
public void createUser() {
getUserfacade().createUser(user);
}
public UserFacade getUserfacade() {
if (userfacade == null){
userfacade = new UserFacade();
}
return userfacade;
}
}
And finally from JSF page I call the method like this:
<f:view>
<h:form>
<h1><h:outputText value="Create/Edit"/></h1>
<h:panelGrid columns="2">
<h:outputLabel value="Username:"/>
<h:inputText id="username" value="#{userMB.user.username}" title="username" />
<h:outputLabel value="Password:" />
<h:inputText id="password" value="#{userMB.user.password}" title="password" />
<h:outputLabel value="ID:" />
<h:inputText id="id" value="#{userMB.user.id}" title="id" />
</h:panelGrid>
<h:commandButton action="#{userMB.createUser}" value="create"/>
</h:form>
</f:view>
Where is my mistake?
@PersistenceContext
works only in managed classes. Your UserDAO
(and UserFacade
) seems to be completely unmanaged and created manually. This way the EntityManager
won't be injected at all. You'd need to manually create it as well. Right now it is null
, which thus explains the NullPointerException
.
Make the UserDAO
(and UserFacade
) a @Stateless
EJB
@Stateless
public class UserDAO {
// ...
}
and use @EJB
to inject them (and remove lazy loading in getter)
@EJB
private UserFacade userFacade; // Also on userDAO.
Or, if your environment doesn't support EJBs (e.g. Tomcat), then you'd need to either upgrade it to TomEE or to install OpenEJB on top of it, or to look for an alternate framework to manage your service facades and DAOs. Spring is often used, but why would you choose for it if Java EE 6 already offers the EJB3 awesomeness?