+

Search Tips   |   Advanced Search

Implement JAX-RS resources with different lifecycle scopes

Application developers can use Java Contexts and Dependency Injection (JCDI) to have different scopes for their managed beans. For instance, if we have an @javax.enterprise.context.ApplicationScoped annotation on a Java class named Foo and multiple @javac.inject.Inject annotated Foo fields in managed beans, there is only one application-scoped Foo instance that actually exists.

Lifecycle scopes can help application developers manage their code. For example, by giving Java types a simple scope annotation, we can ensure that a single, managed instance is created for that scope, instead of having to potentially write multiple lines of code to guarantee the behavior that we want.

Lifecycle scopes only apply to managed beans. If the application code creates a new instance of a class, your code controls the entire lifecycle of that single instance. However, in managed code such as Java API for RESTful Web Services (JAX-RS) resource classes where the runtime environment creates new instances for you, the JAX-RS runtime environment assumes responsibility of the lifecycle of our classes.

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

The following instructions describe how we can use lifecycle scopes for a simple JCDI-enabled web application with JAX-RS:


Tasks

  1. Add a beans.xml deployment descriptor to the web application (WAR) in the WEB-INF directory. The existence of the WEB-INF/beans.xml file indicates that the archive is a JCDI-enabled archive. We are not required to add any additional information to it for this task. The following example illustrates a basic WEB-INF/beans.xml file:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/
    XMLSchema-instance" xsi:schemeLocation="http://java.sun.com/xml/ns/javaee http:/
    /java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    
    <!-- This is empty on purpose. -->
    
    </beans>
    

  2. Create a JAX-RS root resource class. The following example illustrates a simple JAX-RS root resource class:
    package com.example.jaxrs;
    
    @javax.ws.rs.Path("exampleWithLifecycle")
    public class StringResource {
    
        @javax.ws.rs.GET
        @javax.ws.rs.Produces(javax.ws.rs.core.MediaType.TEXT_PLAIN)
        public String get() {
            return "Hello world!";
        }
    }
    

  3. Add a JCDI lifecyle scope to the JAX-RS classes. Add the @javax.enterprise.context.RequestScoped scope annotation to your root resource classes:

    Add the @javax.enterprise.context.RequestScoped annotation to your root resource classes to ensure that the JAX-RS root resource class has a unique instance per request. This is the default behavior in non-JCDI enabled applications.bprac

    package com.example.jaxrs;
    
    @javax.enterprise.context.RequestScoped
    @javax.ws.rs.Path("exampleWithLifecycle")
    public class StringResource {
    
        @javax.ws.rs.GET
        @javax.ws.rs.Produces(javax.ws.rs.core.MediaType.TEXT_PLAIN)
        public String get() {
            return "Hello world!";
        }
    }
    
  4. (optional) For any custom @javax.ws.rs.ext.Provider annotated classes or javax.ws.rs.core.Application subclasses, we must add @javax.enterprise.context.ApplicationScoped to your class. The following example illustrates how to modify the JAX-RS provider or application sub-class with an @javax.enterprise.context.ApplicationScoped scope annotation:
    package com.example.jaxrs;
    
    @javax.enterprise.context.ApplicationScoped
    @javax.ws.rs.ext.Provider
    public class Example implements javax.ws.rs.ext.MessageBodyWriter<CustomType> {
    
        public long getSize(String t,
                            Class<?> type,
                            Type genericType,
                            Annotation[] annotations,
                            javax.ws.rs.core.MediaType mediaType) {
            return -1;
        }
    
        public boolean isWriteable(Class<?> type,
                                   Type genericType,
                                   Annotation[] annotations,
                                   javax.ws.rs.core.MediaType mediaType) {
            return CustomType.class == type;
        }
    
        public void writeTo(String t,
                            Class<?> type,
                            Type genericType,
                            Annotation[] annotations,
                            javax.ws.rs.core.MediaType mediaType,
                            javax.ws.rs.core.MultivaluedMap<String, Object> httpHeaders,
                            OutputStream entityStream) throws IOException {
            /* write something to the entity stream */
        }
    }
    

We have configured a web application to use JCDI, and created a JCDI, lifecycle-scoped JAX-RS resource and provider.

  • Implement a JAX-RS resource with decorators and method interceptors
  • Implement JAX-RS resources with dependency injection
  • Web services specifications and APIs