Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot inject CDI bean into custom validator #3801

Closed
jerseyrobot opened this issue Apr 6, 2018 · 4 comments
Closed

Cannot inject CDI bean into custom validator #3801

jerseyrobot opened this issue Apr 6, 2018 · 4 comments
Labels

Comments

@jerseyrobot
Copy link
Contributor

Jersey doesn't allow me to inject CDI bean into my custom Validator.

Sample code:

@ApplicationScoped
public class AllowedWeightsValidator implements ConstraintValidator<AllowedWeights, Map<String, Integer>> {

    @Inject
    private Localizer localizer;

    @Override
    public void initialize(AllowedWeights allowedWeights) {
        // ...
    }

    @Override
    public boolean isValid(Map<String, Integer> weights, ConstraintValidatorContext context) {
        // ...
    }

}

The exception is:

<org.glassfish.jersey.server.internal.JerseyResourceContext> <BEA-000000> <Lookup and initialization failed for a resource class: class package.AllowedWeightsValidator.
A MultiException has 1 exceptions.  They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=Localizer,parent=AllowedWeightsValidator,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1451781908)

        at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:75)
        at org.jvnet.hk2.internal.Utilities.justInject(Utilities.java:941)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:980)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1055)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1046)
        at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:173)
        at org.glassfish.jersey.server.internal.JerseyResourceContext.getResource(JerseyResourceContext.java:102)
        at org.glassfish.jersey.server.validation.internal.InjectingConstraintValidatorFactory.getInstance(InjectingConstraintValidatorFactory.java:61)
        at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.createAndInitializeValidator(ConstraintValidatorManager.java:141)
        at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.getInitializedValidator(ConstraintValidatorManager.java:101)
        at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:125)
        at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:91)
        at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:83)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:547)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:487)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:451)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:403)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateCascadedConstraint(ValidatorImpl.java:723)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateCascadedConstraints(ValidatorImpl.java:601)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:412)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateCascadedConstraint(ValidatorImpl.java:723)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateCascadedConstraints(ValidatorImpl.java:601)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateParametersInContext(ValidatorImpl.java:992)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:300)
        at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:254)
        at org.glassfish.jersey.server.validation.internal.DefaultConfiguredValidator.onValidate(DefaultConfiguredValidator.java:175)
        at org.glassfish.jersey.server.validation.internal.ValidationInterceptorExecutor.proceed(ValidationInterceptorExecutor.java:113)
        at org.glassfish.jersey.server.validation.internal.DefaultConfiguredValidator.validateResourceAndInputParams(DefaultConfiguredValidator.java:146)
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:134)
        at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:205)
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
        at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326)

Such injection should be according to Beans Validation spec (1.1, section 10.3.2) supported:

If no custom ConstraintValidatorFactory is requested by the user, the ValidatorFactory must be configured with a custom ConstraintValidatorFactory instance that returns CDI managed beans representing the requested ConstraintValidator types

When I inject (via @javax.inject.Inject) the Validator manually, everything works as expected. The problem occurs when I have a JAX-RS @POST method accepting POJO with my custom validation annotation.

This problem can be workarounded by registering the following ContextResolver:

public class ValidationConfigResolver implements ContextResolver<ValidationConfig> {

    @Context
    private ResourceContext resourceContext;

    @Override
    public ValidationConfig getContext(Class<?> aClass) {
        return new ValidationConfig().constraintValidatorFactory(new CDIConstraintValidatorFactory(resourceContext));
    }

    private static class CDIConstraintValidatorFactory implements ConstraintValidatorFactory {

        private final ResourceContext resourceContext;

        public CDIConstraintValidatorFactory(ResourceContext resourceContext) {
            this.resourceContext = resourceContext;
        }

        @Override
        public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> clazz) {
            Instance<T> cdiInstance = CDI.current().select(clazz);
            return cdiInstance.isUnsatisfied() ? resourceContext.getResource(clazz) : cdiInstance.get();
        }

        @Override
        public void releaseInstance(ConstraintValidator<?, ?> constraintValidator) {
            try {
                CDI.current().destroy(constraintValidator);
            } catch (UnsupportedOperationException ignored) {
                // If CDI cannot destroy the validator, that's perfectly fine.
                // It could have been created by HK2 (ResourceContext).
            }
        }
    }

}
@jerseyrobot
Copy link
Contributor Author

@mhorejsi Commented
The affected Jersey version is 2.22.1.

@jerseyrobot
Copy link
Contributor Author

@jansupol Commented
The injection has been significantly reworked in 2.26. Can you reproduce with latest Jersey?

@jerseyrobot
Copy link
Contributor Author

@mhorejsi Commented
I use WebLogic server 12.2.1.2 which bundles Jersey 2.22.1. Once I have some spare time, I'll try to reproduce this issue with the latest Jersey.

@jerseyrobot
Copy link
Contributor Author

@jansupol jansupol added the cdi label May 31, 2018
pdudits added a commit to payara/patched-src-jersey that referenced this issue Apr 17, 2019
pdudits added a commit to payara/patched-src-jersey that referenced this issue Oct 14, 2019
dmatej pushed a commit to payara/patched-src-jersey that referenced this issue Jan 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants