Jersey Inject Weld is driven by a bean at ConstraintValidator
I've searched for hours to find a solution for my problem, but I can't seem to get it to work. I want my Weld managed service to bind to a ConstraintValidator which is used to validate the user object that is sent to the JAX-RS Rest-Service. Everything is deployed to a Glassfish 4.1 server.
I have a Service like this
@ApplicationScoped
public class UserService {
}
and I want to inject it into ConstraintValidator like this
public class UniqueUserNameValidator implements ConstraintValidator<UniqueUserName, ApiUser> {
@Inject
private UserService service;
@Override
public void initialize(UniqueUserName constraintAnnotation) {
}
@Override
public boolean isValid(ApiUser value, ConstraintValidatorContext context) {
return service.getByUserName(value.getUserName()) == null;
}
}
the REST resource looks like this
@Path("users")
@Produces(MediaType.APPLICATION_JSON)
public class UserResource {
@Inject
UserService userService;
@POST
public Response createUser(@Valid ApiUser apiUser) {
ApiRepresentation created = userService.create(apiUser);
return Response.created(createURL(created)).build();
}
}
When I post a custom json object, I get the following exception:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=UserService,parent=UniqueUserNameValidator,qualifiers={},position=-1,optional=false,self=false,unqualified=null,173822971)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)
at org.jvnet.hk2.internal.Utilities.justInject(Utilities.java:947)
at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:902)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:977)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:968)
at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:173)
I know jersey uses hk2 as DI provider and ConstraintValidator is instantiated with InjectingConstraintValidatorFactory , which in turn uses ResourceContext, Since HK2 doesn't know anything about my WELD beans managed container, it can't inject proper service when ConstraintValidator is created.
To fix this I am looking for
a) A way to expose JAX-RS (the preferred pure JAX-RS path without jersey dependency) using a custom ConstraintValidatorFactory to create a validator.
or b) A way to force jersey to use WELD as the DI provider or tell hk2 to load the entire managed container with beans WITHOUT manually adding each bean to hk2. I have no idea how to use the suggested bridge here .
I appreciate any help.
Greetings
source to share
Do you have the option to change the base JAX-RS implementation for your project?
When I had the same problem, I just switched from Jersey to RestEasy (a fully certified JAX-RS implementation). http://resteasy.jboss.org/
Changing the implementation was easy enough: just include the dependency through your favorite build automation tool (I'm using gradle):
compile 'org.jboss.resteasy:resteasy-servlet-initializer:3.0.11.Final'
Also, to make CDI work, enable the CDI restaasy-cdi JAX-RS bridge:
compile 'org.jboss.resteasy:resteasy-cdi:3.0.11.
Finally, if you want the same JSON format, include resteasy-jackson-provider:
compile 'org.jboss.resteasy:resteasy-jackson-provider:3.0.11.Final'
In the end, switching to resteasy gave me a lot less headache than trying to implement a Jersey fix.
source to share