Dependency Injection with HK2 in Jersey and JAX-RS

Adding dependency injection support into Jersey 2 Web Services application that uses HK2 is not very straightforward. So, I created this page to document things I needed to do in my Jersey 2 RESTful Web Services app to make the Dependency Injection work. Hope you will find it useful.

  1. Create a new class that extends AbstractBinder. This class will need to bind classes that participate in Dependency Injection.
    package com.appsdeveloperblog.app.ws;
    
    import com.appsdeveloperblog.app.ws.service.UserService;
    import com.appsdeveloperblog.app.ws.service.impl.UserServiceImpl;
    import com.appsdeveloperblog.com.app.ws.io.repositories.UserRepository;
    import org.glassfish.hk2.utilities.binding.AbstractBinder;
    
    /**
     *
     * @author skargopolov
     */
    public class MyApplicationBinder extends AbstractBinder {
        @Override
        protected void configure() {
            bind(UserServiceImpl.class).to(UserService.class);
            bind(UserRepository.class).to(UserRepository.class);
        }
    }
    
  2. Create a new class that extends ResourceConfig. This class will be used to register a class that extends AbstractBinder. An example of this class is above and in my case, it is called MyApplicationBinder.
    package com.appsdeveloperblog.app.ws;
     
    import org.glassfish.jersey.server.ResourceConfig;
    
    /**
     *
     * @author skargopolov
     */
    public class App extends ResourceConfig{
        public App() {
           packages("com.appsdeveloperblog.app.ws");
           register(new MyApplicationBinder());  
        }
    }

     

  3. Updated Root Resouce class to Inject the service. Notice the @Inject annotation above the UserService. This annotation is required for UserService class to be injected into this Root Resource class.

    @Path("users")
    public class Users {
        
        public Users(){}
        
        @Inject
        UserService userService;
         
        @POST
        @Consumes({ MediaType.APPLICATION_JSON,  MediaType.APPLICATION_XML} )
        @Produces({ MediaType.APPLICATION_JSON,  MediaType.APPLICATION_XML} )
        public UserProfileRest createUser(CreateUserModelRest createUserModel) {
            UserProfileRest returnValue = new UserProfileRest();
            UserProfileDto userDto = new UserProfileDto();
          
            BeanUtils.copyProperties(createUserModel, userDto);
            
            UserProfileDto createdUserDto = userService.createUser(userDto);
            
            BeanUtils.copyProperties(createdUserDto, returnValue);
            
            return returnValue;
        }
    
    }

    If you want to use BeanUtils as in my code above then add the below dependency to your pom.xml file:

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-beans</artifactId>
         <version>4.3.7.RELEASE</version>
     </dependency>

     

  4. Update Service layer classes. If you would like your Service layer class to also use Dependency Injection update then use Constructor-based dependency injection as shown below. Do not forget to bind this class in a MyApplicationBinder as shows in the MyApplicationBinder class above.
    package com.appsdeveloperblog.app.ws.service.impl;
    
    import com.appsdeveloperblog.app.ws.service.UserService;
    import com.appsdeveloperblog.app.ws.shared.dto.UserProfileDto;
    import com.appsdeveloperblog.com.app.ws.io.repositories.UserRepository;
    import java.util.List;
    import javax.inject.Inject;
    
    /**
     *
     * @author skargopolov
     */
    public class UserServiceImpl implements UserService {
        
        UserRepository userRepository;
        
        @Inject
        public UserServiceImpl(UserRepository userRepository)
        {
            this.userRepository = userRepository;
        }
    
        @Override
        public UserProfileDto createUser(UserProfileDto user) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }
    }

     

  5. Update your web.xml file which is in WEB-INF folder. If your web.xml file does not have the two init-param which are below, then add them. The first init-param’s value is the root package name which contains your JAX-RS resources. And the second init-param value is the complete package name of your App.java file. Please note that it is a package name + class name.
    <init-param>
         <param-name>jersey.config.server.provider.packages</param-name>
         <param-value>com.appsdeveloperblog.app.ws</param-value>
     </init-param>
     <init-param>
         <param-name>javax.ws.rs.Application</param-name>
          <param-value>com.appsdeveloperblog.app.ws.App</param-value>
     </init-param>

    Below is my complete web.xml file which contains these two init params:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- This web.xml file is not required when using Servlet 3.0 container,
         see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
        <servlet>
            <servlet-name>Jersey Web Application</servlet-name>
            <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>jersey.config.server.provider.packages</param-name>
                <param-value>com.appsdeveloperblog.app.ws</param-value>
            </init-param>
            <init-param>
                <param-name>javax.ws.rs.Application</param-name>
                 <param-value>com.appsdeveloperblog.app.ws.App</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
     
        <servlet-mapping>
            <servlet-name>Jersey Web Application</servlet-name>
            <url-pattern>/webapi/*</url-pattern>
        </servlet-mapping>
    </web-app> 

 

How would it change your life if you knew how to build RESTful Web Services with Jersey and JAX-RS very well? I know from my personal experience that learning on the internet by reading programming tutorial is not the fastest way to progress. Below is a list of step by step video courses that might help you learn most of the things you need about Jersey and JAX-RS and feel much more confident as a RESTful Web Services developer!

Learning RESTful Web Services Development


Leave a Reply

Your email address will not be published. Required fields are marked *