Using CDI + WS/RS + JPA to build an app
@Path(value = "/user")
@Stateless
public class UserService {
@Inject
private UserManager manager;
@Path(value = "/create")
@GET
@Produces(value = MediaType.TEXT_PLAIN)
public String doCreate(@QueryParam(value = "name") String name) {
manager.createUser(name);
return "OK";
}
}
here is the user manager impl
public class UserManager {
@PersistenceContext(unitName = "shop")
private EntityManager em;
public void createUser(String name) {
User user = new User();
user.setName(name);
// skip some more initializations
em.persist(user);
}
}
the problem is if i do not mark UserService as @Stateless then the manager field is null
but if i mark @Stateless, i can have the manager field injected, and the application works as i can get the data saved into db
just wondering, what is the reason behind this?
and is this the preferred way to开发者_运维知识库 wiring the application?
well, i am thinking to pull out the EntityManager to a producer, so that it can be shared
the problem is if I do not mark UserService as @Stateless then the manager field is null
For injection to occur, the class has to be a managed component such as Enterprise Beans, Servlets, Filters, JSF managed beans, etc or CDI managed bean (this is the new part with Java EE 6, you can make any class a managed bean with CDI).
So, if you don't make your JAX-RS endpoint an EJB, how to enable injection? This is nicely explained in JAX-RS and CDI integration using Glassfish v3:
There are two ways CDI managed beans are enabled:
instantiated by CDI, life-cycle managed by Jersey. Annotate with
@ManagedBean
and optionally annotate with a Jersey scope annotation.instantiated and managed by CDI. Annotate with a CDI scope annotation, like
@RequestScoped
(no@ManagedBean
is required)
I also suggest checking the resources below.
and is this the preferred way to wiring the application?
I'd say yes. CDI is very nice and... don't you like injection?
well, I am thinking to pull out the EntityManager to a producer, so that it can be shared
Shared between what? And why? In you case, you should use an EntityManager
with a lifetime that is scoped to a single transaction (a transaction-scoped persistence context). In other words, don't share it (and don't worry about opening and closing it for each request, this is not an expensive operation).
References
- JPA 2.0 Specification
- Section 7.6 "Container-managed Persistence Contexts"
- Section 7.6.1 "Container-managed Transaction-scoped Persistence Context"
- Section 7.6.2 "Container-managed Extended Persistence Context"
Resources
- Dependency Injection in Java EE 6 - Part 1
- Introducing the Java EE 6 Platform: Part 1
- TOTD #124: Using CDI + JPA with JAX-RS and JAX-WS
The @Singleton annotation will help: http://www.mentby.com/paul-sandoz/jax-rs-on-glassfish-31-ejb-injection.html
精彩评论