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.
- 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); } }
- 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()); } }
- 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>
- 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. } }
- 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