Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 745
Dapeng Avatar asked Sep 19 '10 03:09

Dapeng


1 Answers

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

  • 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
like image 70
Pascal Thivent Avatar answered Sep 28 '22 07:09

Pascal Thivent