Jersey Injection Dependency example with HK2

Step 1: Starting a new Jersey Project

Generate a project from Maven Archetype:

mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-grizzly2 \
-DarchetypeGroupId=org.glassfish.jersey.archetypes -DinteractiveMode=false \
-DgroupId=com.example -DartifactId=simple-service -Dpackage=com.example \
-DarchetypeVersion=2.29.1

Step 2: Business Logic

Add some business logic to make this test more interesting in com.example.business:

  • User
  • UserSvc
  • UserDao

Step 3: Automatically bind classes to their implementation

We want to be able to do Dependency Injection of our services. We need to register a AbstractBinder to our jersey app that will automatically match the given injected class with the implementation.

@Provider
public class ApplicationBinder extends AbstractBinder {
@Override
protected void configure() {
bind(JustInTimeServiceResolver.class).to(JustInTimeInjectionResolver.class);
}
resourceConfig.register(new ApplicationBinder());
@Service
public class JustInTimeServiceResolver implements JustInTimeInjectionResolver {

@Inject
private ServiceLocator serviceLocator;

@Override
public boolean justInTimeResolution(Injectee injectee) {
final Type requiredType = injectee.getRequiredType();

if (injectee.getRequiredQualifiers().isEmpty() && requiredType instanceof Class) {
final Class<?> requiredClass = (Class<?>) requiredType;

// IMPORTANT: check the package name, so we don't accidentally preempt other framework JIT resolvers
if (requiredClass.getName().startsWith("com.example")) {
final List<ActiveDescriptor<?>> descriptors = ServiceLocatorUtilities.addClasses(serviceLocator, requiredClass);

return !descriptors.isEmpty();
}
}
return false;
}
}
@GET
@Path("users")
@Produces(MediaType.APPLICATION_JSON)
public List<User> getUsers() {
return userSvc.getList();
}
@Inject
private UserSvc userSvc;
@Inject
private UserDao userDao;
@Test
public void testGetUsers() {
List<User> users = target.path("myresource/users").request().get(new GenericType<List<User>>() {});
assertEquals(2, users.size());
}

Step 4: Extract the user from the JWT Token and make it available for injection with a custom annotation

Now we would like to be able to get information about the user that send requests to our API and use it where needed in our application.
Our API will have secured access managed by a JWT Token.

@PreMatching
@Priority(Priorities.AUTHENTICATION)
public class PreMatchingCurrentUserFilter implements ContainerRequestFilter {

@Override
public void filter(ContainerRequestContext requestContext) {
try {
Jws<Claims> jws = new AuthorizationValidator(false).validate(requestContext);
AppSecurityContext appSecurityContext = new AppSecurityContext(
new HashSet<String>(),
new User(
(String) jws.getBody().get("login"),
(String) jws.getBody().get("compte")
),
true
);
requestContext.setSecurityContext(appSecurityContext);
}
catch (Exception ignored) {
}
}
}
resourceConfig.register(new PreMatchingCurrentUserFilter());
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.CONSTRUCTOR})
public @interface CurrentUser {
}
public class CurrentUserInjectionResolver implements InjectionResolver<CurrentUser> {

private javax.inject.Provider<SecurityContext> securityContextProvider;

@Inject
public CurrentUserInjectionResolver(
javax.inject.Provider<SecurityContext> securityContextProvider) {
this.securityContextProvider = securityContextProvider;
}

@Override
public Object resolve(Injectee injectee, ServiceHandle<?> sh) {
if (User.class == injectee.getRequiredType()) {
return securityContextProvider.get().getUserPrincipal();
}
return null;
}

...
}
@CurrentUser
private User user;
@CurrentUser
public UserSvc(User user){
this.user = user;
}

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store