4

I've seen a bunch of times several ways a JAXRS resource is configured.

I mean, sometimes I see they are annotated as @Singleton, @Stateless, @ApplicationScoped, @RequestScoped, and even without any annotation or using both of them.

  • javax.enterprise.context.RequestScoped
  • javax.enterprise.context.ApplicationScoped
  • javax.ejb.Stateless
  • javax.ejb.Singleton
  • javax.inject.Singleton

Which annotation should I use?

What has javax.ejb to do with a JAXRS resource?

By other hand, I'd also like to know about how to work exactly with @Context annotation.

I mean, I've seen this applied on a parameter, also in a class field.

@Path("entity")
public class EntityResource {

    @Context
    private Request request;

    @POST
    public Response create(Entity entity) {
        this.request...
    }

}

or,

@Path("entity")
public class EntityResource {

    @POST
    public Response create(Entity entity, @Context Request request) {
        request...
    }

}

How would i proceed?

Jordi
  • 20,868
  • 39
  • 149
  • 333

3 Answers3

7

There is no need to use any EJB or CDI annotations in a JAX-RS resource class - unless you want to use EJB or CDI features in the same class.

If you want to inject any CDI bean into the resource classes, then the resource class must be a CDI bean itself, so you should add a scope annotation, preferably @javax.enterprise.context.RequestScoped.

If you use an EJB annotation like @Stateless, injection will also work, since EJBs are also CDI beans (but not the other way round). However, a stateless beans has a different lifecycle, and it is transactional by default.

On the other hand, if you need transactions, you can also use @javax.transaction.Transctional in combination with @RequestScoped and @Path.

Background:

EJBs are a bit out-dated for most purposes. They came first, before JAX-RS and CDI, but these days, CDI is regarded as the unifying dependency injection mechanism in Java EE/Jakarta EE, and older specs are in the process of being updated to get more tightly integrated with CDI.

Harald Wellmann
  • 12,615
  • 4
  • 41
  • 63
  • 1
    why "preferably RequestScoped"? – user1075613 Mar 17 '19 at 00:54
  • 4
    Because each JAX-RS resource method invocation corresponds to an HTTP request. If you use a longer-lived scope, your class must be thread-safe. – Harald Wellmann Mar 17 '19 at 16:18
  • Regarding this: "If you want to inject any CDI bean into the resource classes, then the resource class must be a CDI bean itself, so you should add a scope annotation": that's not fully correct, JAX-RS resources and providers are not CDI beans, since they are not instantiated by CDI but by JAX-RS. For the same reason they do not need a scope annotation: JAX-RS decides their scope in a hardcoded way (request-scoped for resources, application-scoped for providers). JAX-RS integrates with CDI in the sense that it allows these objects it creates to have CDI-managed dependencies. – jsiwrk Oct 18 '21 at 16:23
  • See also this answer: https://stackoverflow.com/a/17911683/10202182 – jsiwrk Oct 18 '21 at 16:24
2

Regarding your 1st question (managed bean scope), I'd say that no scope annotation should be used as the java-ee container will manage automatically the right scope for your bean according to the Jax-rs annotation.

However the guys from ibm seems to have a different idea of the question and state the following

Best practice

Add specific lifecycle scopes to any JAX-RS root resource and provider classes that exist in your application, in a JCDI-enabled archive. For JAX-RS resource classes with an @javax.ws.rs.Path annotation, you can use @javax.enterprise.context.RequestScoped. For javax.ws.rs.core.Application sub-classes and @javax.ws.rs.ext.Provider annotated classes, you must use @javax.enterprise.context.ApplicationScoped.

Regarding the @Context annotation it's used to inject objects related to the current http request (you can find a list of injectable instances here) and you can use it on both instance fields and method parameters

Community
  • 1
  • 1
Gab
  • 7,869
  • 4
  • 37
  • 68
  • Can be a JAX-RS Resource an EJB Resource? – Jordi Feb 06 '19 at 08:52
  • Jax-rs has his own container https://docs.oracle.com/javaee/7/api/javax/ws/rs/container/package-summary.html which seems to be implemented on top of servlet one https://stackoverflow.com/questions/41397075/is-jax-rs-built-on-top-of-servlet-api-how. Honestly I don't know which container manages the bean when you put both jax-rs and EJB annotation on your class, I suspect that the EJB annotation is just ignored but this must depend on your server implementation – Gab Feb 06 '19 at 09:26
  • 1
    "The java-ee container will manage automatically the right scope for your bean according to the Jax-rs annotation" - this is not true. JAX-RS has its own notion of scope (see javax.ws.rs.core.Application.getClasses() vs. getSingletons()), but a JAX-RS resource is not a CDI bean by default, unless you add a bean defining annotation, or work with bean-discovery-mode="all". – Harald Wellmann Mar 16 '19 at 22:24
  • How should I set a JAX-RS resource is a CDI bean? Is there any CDI specific related annotations bean? `@Stateless` is available on microprofile? – Jordi Mar 20 '19 at 10:51
  • No `@Stateless` is part of EJB spec which is not part of micro profile, as stated by Herald you can use any CDI "bean defining annotation", a scope one (`@ApplicationScoped`, `@SessionScoped`, `@ConversationScoped`, `@RequestScoped`) is preferred (otherwise the bean will use the `@Dependent` pseudo scope) – Gab Mar 20 '19 at 12:46
0

Using @Stateless on a JAX-RS resource can be good to prevent the web server from creating a new Resource for each call (as it's done using the @RequestScoped annotation). When using the @Stateless annotation, the server will create a pool of resources which can be configurable. You will also get benefits of transactions.

Rouliboy
  • 1,377
  • 1
  • 8
  • 21
  • What about `ApplicationScoped` then. I mean, Which's the difference between `@ApplicationScoped` and `@Stateless` then? – Jordi Mar 20 '19 at 10:47
  • @Jordi : Using a pool (i.e using `@Stateless`), you can control the traffic on your app (as a single http call will be attached to a single stateless resource). However, with application scoped bean, you can't control incoming request traffic. None is better than the other, it just depends on what you want to do. – Rouliboy Mar 20 '19 at 13:04