JAX-RS Resource as Session Bean or CDI Managed Bean?

6

Today I ran into an interesting problem when trying to inject an EJB into a JAX-RS resource (in GlassFish 4.1, running the preinstalled version of Jersey).

@Stateless
public class MeuEJB implements MinhaInterface {
   // código
}

@Path("caminho")
public class MeuRecurso {
    @Inject
    private MinhaInterface minhaInterface;   
   // código
}

When trying to access the resource, it received a 500 Internal Server Error saying that there were no valid candidates for MinhaInterface injection.

Trying to dig deeper into the subject I discovered that since Jersey version 2.0 it includes an IoC library called HK2 . This container apparently knows nothing a priori about the CDI or EJB scopes.

An obvious alternative is to do the jndi lookup manually. In addition, there are solutions with InjectionManager and SPI.

That said, the Java EE 7 tutorial gives two recipes to integrate JAX-RS with EJB.

  • Transform the resource into an EJB:

    @Path("caminho")
    @Stateless
    public class MeuRecurso {
        @EJB
        private MinhaInterface minhaInterface;   
        // código
    }
    
  • Transform the resource into a CDI bean:

    @Path("caminho")
    @RequestScoped
    public class MeuRecurso {
        @Inject
        private MinhaInterface minhaInterface;   
        // código
    }
    
  • Both alternatives work correctly. What I would like to know from an architectural (and practical) point of view is: What are the implications of turning my JAX-RS resource into a Stateless Session Bean or a CDI Managed Bean in>? Have best practices been defined on this front?

        
    asked by anonymous 26.09.2014 / 23:09

    2 answers

    5

    There are some differences between using a JAX-RS endpoint as a CDI bean / Stateless bean or not using either of these. From a practical point of view, I do not see much differentiation between which to use, CDI or EJB, other than the ones already known Differences between them .

    Below are two practical points that are the most important:

  • Transaction Propagation: Both with the @TransactionAttribute (EJB) or @Transactional (CDI) give the possibility to encapsulate the transaction and define whether it will be propagated to "levels / layers / dependency or whatever" minor, for example you can define that a single request will be fully wrapped in a transactional unit.
  • JAAS security features (EJB only) right in your resources, with @RolesAllowed you can define your basic security scheme without any additional work.
  • Dependency injection: This is the same for both, as you have seen yourself.
  • Direct access to EntityManager (and any other resource, JMS, JCA etc): In simple CRUD cases, I do not see why swell the code and use a 3-layer pattern (etc) to do this, in this practical point, use a em.merge(...) directly in its JAX-RS class, greatly simplifies life.
  • In short, the question of having a JAX-RS with EJB or JAX-RS with CDI does not change anything unless you have to use some of the specific features of these two APIs. instances between using it or not, I see it's pretty much the same since jaxrs endpoints are already managed by the container.

    Go from CDI until you need to use some specific EJB feature. Although it does not have a big performance difference these days. ( REF ).

        
    28.09.2014 / 13:11
    1

    There is no such need, the JAX-RS specification already defines that the life cycle of a resource is per request. It does not make sense to mark it as @Stateless, by default it has no state.

    I think you have not yet defined good practice for this. I use CDI with @Inject, it is enough for my needs within a resource.

        
    25.02.2015 / 19:57