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

+3


source to share


2 answers


I also ran into this problem with Jersey 2.25.x, Weld 2.4.x and Tomcat 8.x and have not found the correct solution since @Inject

.

As a workaround, I programmatically looked for the bean instance using:



SomeSortOfBean bean = CDI.current().select(SomeSortOfBean.class).get();

      

+1


source


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.

0


source







All Articles