views:

43

answers:

1
@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

+1  A: 

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:

  1. instantiated by CDI, life-cycle managed by Jersey. Annotate with @ManagedBean and optionally annotate with a Jersey scope annotation.

  2. 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

Pascal Thivent
very nice and detailed answer, one more thing to clarify, the 'sharing' of the EM, suppose i have another OrderService which uses the same PU, i don't want to repeat the @PersistenceContext(unitName = "shop") rather i'd want to have it as @Inject EntityManager, how could i do it?
Dapeng
@Dapeng AFAIK, you don't need to specify the `unitName` in `@PersistenceContext` if there is only one persistence unit defined in the scope of the component which is using `@PersistenceContext`, otherwise you need to specify it.
Pascal Thivent
thx for the reply, i will try out first
Dapeng