RESTEasy, CDI, embedded Jetty, bean validation is

2019-06-14 02:37发布

I've a Groovy project where I use RESTEasy with Weld and deploy to embedded Jetty. What I can't seem to get working is bean validation. RESTEasy documentation says that adding resteasy-validator-provider-11 along with hibernate validator dependencies (hibernate-validator, hibernate-validator-cdi, javax.el-api, javax.el) is enough. But the bean validation is simply ignored by RESTEasy. I curiously also get the following message in the logs:

plugins.validation.ValidatorContextResolver - Unable to find CDI supporting ValidatorFactory. Using default ValidatorFactory

Based on the suggestions on [this][1] post, I tried registering Hibernate InjectingConstraintValidatorFactory in META-INF/validation.xml but it depends on a BeanManager being injected and blows up at runtime.

The code can be found here https://github.com/abhijitsarkar/groovy/tree/master/movie-manager/movie-manager-web

A log gist is here: https://gist.github.com/anonymous/8947319

I've tried everything under the sun without any success. Pls help.

2条回答
劫难
2楼-- · 2019-06-14 03:04

To do this without EE, I believe you'll need to fork the existing InjectingConstraintValidatorFactory but instead of using injection of the bean manager, use the CDI 1.1 class CDI to get a reference to the bean manager, e.g. CDI.current().getBeanManager(). http://docs.jboss.org/cdi/api/1.1/javax/enterprise/inject/spi/CDI.html

You do need to be on CDI 1.1 to do this (so Weld 2+, 2.1.1 is current I believe). Here's an example impl, based on: https://github.com/hibernate/hibernate-validator/blob/master/cdi/src/main/java/org/hibernate/validator/internal/cdi/InjectingConstraintValidatorFactory.java

    public class InjectingConstraintValidatorFactory implements ConstraintValidatorFactory {
        // TODO look for something with better performance (HF)
        private final Map<Object, DestructibleBeanInstance<?>> constraintValidatorMap =
                Collections.synchronizedMap( new IdentityHashMap<Object, DestructibleBeanInstance<?>>() );

        private final BeanManager beanManager;

        public InjectingConstraintValidatorFactory() {
            this.beanManager = CDI.current().getBeanManager();
            Contracts.assertNotNull( this.beanManager, "The BeanManager cannot be null" );
        }

        @Override
        public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
            DestructibleBeanInstance<T> destructibleBeanInstance = new DestructibleBeanInstance<T>( beanManager, key );
            constraintValidatorMap.put( destructibleBeanInstance.getInstance(), destructibleBeanInstance );
            return destructibleBeanInstance.getInstance();
        }

        @Override
        public void releaseInstance(ConstraintValidator<?, ?> instance) {
            DestructibleBeanInstance<?> destructibleBeanInstance = constraintValidatorMap.remove( instance );
            destructibleBeanInstance.destroy();
        }
    }
查看更多
\"骚年 ilove
3楼-- · 2019-06-14 03:11

I finally fixed this. Turns out, a validation.xml is not really required, resteasy-cdi module does a fine job of registering the BeanManager. What I was missing and not clearly documented anywhere, is that if an annotation is placed on a method, the validation engine just "decides" what should be validated. I placed a @NotNull on a method and it was validating the return type, not the parameters. One can use validationAppliesTo element in some cases but @NotNull doesn't have it. When I moved it from the method to the parameter, it started working. Now I ran across what I believe is a Weld bug but I'll post that question separately.

查看更多
登录 后发表回答