+

Search Tips   |   Advanced Search

Implement JAX-RS resources with dependency injection

Java Contexts and Dependency Injection (JCDI) supports dependency injection in managed beans. By configuring the web application to be JCDI-enabled, we can add @javax.inject.Inject annotated fields and properties. If the annotated fields and properties are valid injection points with valid JCDI managed beans, then their dependencies will be resolved during run time. Dependency injection separates the creation of new instances of Java types from the use of those Java types in the code. Dependency injection can allow for more easily testable code while also improving the ability to manage applications.

In this task, we configure the application to use JCDI by adding a beans.xml deployment descriptor. Then, we create a standard Java API for RESTful Web Services (JAX-RS) resource type with a @javax.inject.Inject field, which will be resolved during run time.

The following instructions describe how we can create 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. This indicates that the web application should be a JCDI-enabled application. 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 the deployment descriptor 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("exampleWithInjection")
    public class StringResource {
        public StringResource() {
            /* use a no-argument constructor */
        }
    
        @javax.ws.rs.core.Context
        private javax.ws.rs.core.HttpHeaders httpHeaders;
    
        @javax.annotation.PostConstruct
        private void myPostConstruct() {
            /* read from the httpHeaders if required */
        }
    
        @javax.ws.rs.GET
        @javax.ws.rs.Produces(javax.ws.rs.core.MediaType.TEXT_PLAIN)
        public String get() {
            return "Hello world!";
        }
    }
    

    In the previous code, a no-argument constructor was used. A no-argument constructor is a valid JCDI constructor, which makes the class a valid JCDI bean. To inject JAX-RS context objects or parameters during object instantiation, we can use bean properties or fields. Then use an @javax.annotation.PostConstruct annotated method, which is called after the object is constructed.

  3. Add a JCDI lifecycle scope to the JAX-RS classes. The following example illustrates a JAX-RS root resource class with an @javax.enterprise.context.RequestScopedscope annotation:

    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.ws.rs.Path("exampleWithInjection")
    @javax.enterprise.context.RequestScoped
    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. Create a class injected into the JAX-RS root resource. The following example illustrates a standard Java class:
    package com.example.jaxrs;
    
    public class Data {
        public String getData() {
            return "Hello world!";
        }
    }
    

  5. Modify the JAX-RS root resource to add an @javax.inject.Inject annotated field for the com.example.jaxrs.Data type. The following example illustrates a modified JAX-RS root resource class with an @javax.inject.Inject injection point:
    package com.example.jaxrs;
    
    @javax.ws.rs.Path("exampleWithInjection")
    @javax.enterprise.context.RequestScoped
    public class StringResource {
    
        @javax.ws.rs.GET
        @javax.ws.rs.Produces(javax.ws.rs.core.MediaType.TEXT_PLAIN)
        public String get() {
            return myData.getData();
        }
    
        @javax.inject.Inject
        private Data myData;
    }
    

    During run time, when the JAX-RS root resource is constructed, an instance of the Data type is injected into the myData field. While this is a simple form of injection, JCDI allows for more complex use cases. Read the JCDI specification for additional details.

  6. Add a Servlet 3.0 web.xml file to your WAR file. In the following example, a default JAX-RS application servlet definition is added, which makes all JAX-RS root resources available in the /rest/* URL pattern:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/
    XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/
    j2ee/web-app_3_0.xsd" version="3.0">
        <servlet>
            <servlet-name>javax.ws.rs.core.Application</servlet-name>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>javax.ws.rs.core.Application</servlet-name>
            <url-pattern>/rest/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

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

  • Implement a JAX-RS resource with decorators and method interceptors
  • Implement JAX-RS resources with different lifecycle scopes
  • Web services specifications and APIs