-
1. Re: RESTEASY-1008: Collision between CDI and Bean Validation
jharting Jan 27, 2014 2:57 AM (in response to ron_sigal)My understanding is that this only happens when you validate a JAX-RS resource that you @Inject into another resource, is that correct?
Either way:
1) There is not portable way of unwrapping the proxy. Note that client proxies work lazily which means that there may be no instance to unwrap until a method is actually invoked on the proxy.
2) Currently I do not think there is a way of obtaining the JaxrsInjectionTarget. ResteasyCdiExtension could be modified to expose the modified InjectionTargets.
-
2. Re: RESTEASY-1008: Collision between CDI and Bean Validation
jharting Jan 27, 2014 3:03 AM (in response to jharting)Actually, looking at the reproducer this may be a BV integration issue. When is the validation performed?
-
3. Re: RESTEASY-1008: Collision between CDI and Bean Validation
ron_sigal Feb 5, 2014 9:50 PM (in response to jharting)Hi Josef,
re: "My understanding is that this only happens when you validate a JAX-RS resource that you @Inject into another resource, is that correct?"
In the example I've been using, the resource isn't injected anywhere.
re: "There is not portable way of unwrapping the proxy. Note that client proxies work lazily which means that there may be no instance to unwrap until a method is actually invoked on the proxy."
This isn't the first time I've wished that I could access the object behind a proxy. I guess the semantics would have to require the proxy to create a backing object on demand if it doesn't exist. Is this something Weld could support? Has anyone else asked for it?
re: "ResteasyCdiExtension could be modified to expose the modified InjectionTargets."
Looking at JaxrsInjectionTarget again, I see that inject() receives the actual object from Weld, so I'm not sure that remembering a JaxrsInjectionTarget would help me if I don't have access to that object.
re: "When is the validation performed?"
ResourceMethodInvoker.invoke() calls
Object target = resource.createResource(request, response, resourceMethodProviderFactory);
which then calls
Object obj = constructorInjector.construct(request, response);
propertyInjector.inject(request, response, obj);
Shortly afterward, ResourceMethodInvoker.invokeOnTarget() validates the property and class constraints. Then, MethodInjectorImpl.invoke() validates the method parameters. If no violations are detected, the method is invoked and then the return value is validated.
-
4. Re: RESTEASY-1008: Collision between CDI and Bean Validation
jharting Feb 6, 2014 5:00 AM (in response to ron_sigal)Did you consider implementing validation using CDI interceptors instead?
-
5. Re: RESTEASY-1008: Collision between CDI and Bean Validation
ron_sigal Feb 6, 2014 10:25 PM (in response to jharting)Hmmm, no I didn't think about using CDI interceptors. In general, it wouldn't work because Resteasy has to be able to run in standalone mode. But if CDI is enabled, it would be OK. I suppose that injection into the resource would be done by the time the interceptor runs. This is very promising. Thanks, Jozef.
-
6. Re: RESTEASY-1008: Collision between CDI and Bean Validation
abhi0123 Feb 11, 2014 2:32 AM (in response to ron_sigal)I'm not trying to piggyback on this post but I've a very similar problem described here. Should I ask a question separately or can we discuss here?
-
7. Re: RESTEASY-1008: Collision between CDI and Bean Validation
ron_sigal Feb 13, 2014 6:29 PM (in response to abhi0123)Hi Abhijit,
I think these are different problems, but the jury's out on whether they are related. I'm making progress on Jozef's interceptor, and when I've got something, I'll attach some jars here so you can see if the fix to RESTEASY-1008 helps with your problem.
-Ron
-
8. Re: RESTEASY-1008: Collision between CDI and Bean Validation
ron_sigal Mar 17, 2014 2:31 PM (in response to ron_sigal)Hi Jozef,
I've gotten back to this issue lately, and the interceptor idea worked out pretty well. I've got an interceptor with a binding annotation, and a CDI extension that wraps each resource class with an AnnotatedType which adds the binding annotation.
I'm having one problem, though. If I include the jar with the CDI extension, interceptor, annotation, etc., in the war file, everything works. But if I put the jar into the modules directory, the interceptor gets ignored. I can see that the CDI extension detects the interceptor and adds the binding annotation to the test resource, but the interceptor isn't getting called. Do you know if this has something to do with the jars in the modules directory being processed differently, or am I just doing something wrong?
Thanks,
Ron
-
9. Re: RESTEASY-1008: Collision between CDI and Bean Validation
ron_sigal Mar 22, 2014 11:16 PM (in response to ron_sigal)Hi Jozef,
I've switched from CDI interceptors to old school interceptors bound by the @Interceptors annotation, and now everything is working in WildFly 8 when I put the interceptor in the modules directory.
But I've got two problems when I try to do the same thing in AS 7.
1. I want to inject the ServletContext and ServletRequest into the interceptor. It works fine in WF 8, with Weld 2.1.2, but not in AS 7 with Weld 1.1.5.AS71, which doesn't natively support injection of the ServletContext and ServletRequest. I've got producer methods that create the ServletContext and ServletRequest, and it works fine when I put the interceptor and other classes in the WAR, but not when I put them in the modules directory. I get
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type ServletContext with qualifiers @ResteasyValidationCDIProducerBinding
at injection point [BackedAnnotatedField] @Inject @ResteasyValidationCDIProducerBinding private org.jboss.resteasy.plugins.validation.cdi.ResteasyValidationCdiInterceptor.context
at org.jboss.resteasy.plugins.validation.cdi.ResteasyValidationCdiInterceptor.context(ResteasyValidationCdiInterceptor.java:0)
WELD-001475: The following beans match by type, but none have matching qualifiers:
- WELD|AbstractSyntheticBean|org.jboss.resteasy.resteasy-validation-cdi:main.additionalClasses|ServletContext
2. The other problem seems to be related to my wrapping AnnotatedType:
public class ResteasyValidationCdiAnnotatedType<TYPE> implements AnnotatedType<TYPE>
{
public abstract static class InterceptorQualifer extends AnnotationLiteral<Interceptors> implements Interceptors
{
}
public static final Annotation interceptors = new InterceptorQualifer()
{
public Class[] value()
{
return new Class[] {ResteasyValidationCdiInterceptor.class};
}
};
private AnnotatedType<TYPE> delegate;
private Set<Annotation> annotations = new HashSet<Annotation>();
public ResteasyValidationCdiAnnotatedType(AnnotatedType<TYPE> delegate)
{
this.delegate = delegate;
this.annotations.addAll(delegate.getAnnotations());
this.annotations.add(interceptors);
}
...
Again, it works fine in WF 8, but in AS 7 I get
2:11:57,999 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-8) MSC00001: Failed to start service jboss.deployment.unit."RESTEASY-1008.war".WeldService: org.jboss.msc.service.StartException in service jboss.deployment.unit."RESTEASY-1008.war".WeldService: org.jboss.weld.exceptions.DeploymentException: WELD-000826 Cannot access values() on annotation
at org.jboss.as.weld.services.WeldService.start(WeldService.java:83)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) [rt.jar:1.6.0_41]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) [rt.jar:1.6.0_41]
at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_41]
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-000826 Cannot access values() on annotation
at org.jboss.weld.util.reflection.SecureReflections.extractValues(SecureReflections.java:431)
at org.jboss.weld.bean.AbstractClassBean.initInterceptionModelForType(AbstractClassBean.java:263)
at org.jboss.weld.bean.ManagedBean.initializeAfterBeanDiscovery(ManagedBean.java:343)
at org.jboss.weld.bootstrap.BeanDeployment.doAfterBeanDiscovery(BeanDeployment.java:216)
at org.jboss.weld.bootstrap.BeanDeployment.afterBeanDiscovery(BeanDeployment.java:208)
at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:352)
at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:82)
at org.jboss.as.weld.services.WeldService.start(WeldService.java:76)
... 5 more
Caused by: java.lang.RuntimeException: java.lang.NullPointerException
at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:154)
at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:309)
at org.jboss.weld.util.reflection.SecureReflections.extractValues(SecureReflections.java:428)
... 12 more
Caused by: java.lang.NullPointerException
at org.jboss.weld.util.reflection.SecureReflections$15.work(SecureReflections.java:316)
at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:52)
at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:137)
... 14 more
The message isn't very explicit, but I've only got one AnnotationLiteral in the module.
Any ideas?
Thanks,
Ron
-
10. Re: RESTEASY-1008: Collision between CDI and Bean Validation
ron_sigal Mar 25, 2014 2:14 AM (in response to ron_sigal)Ok, I see where the second problem is coming from. org.jboss.weld.bean.AbstractClassBean.initInterceptionModelForType() includes the code:
// initialize EJB3 interceptors Class<?>[] classDeclaredInterceptors = null; if (getWeldAnnotated().isAnnotationPresent(InterceptionUtils.getInterceptorsAnnotationClass())) { Annotation interceptorsAnnotation = getType().getAnnotation(InterceptionUtils.getInterceptorsAnnotationClass()); classDeclaredInterceptors = SecureReflections.extractValues(interceptorsAnnotation); } getWeldAnnotated() gets an instance of WeldClassImpl, whose annotationMap includes the @Interceptors annotation I added in the wrapping AnnotatedType. But getType() gets the actual resource class, which doesn't have the @Interceptors annotations. So interceptorsAnnotation is null, leading to a NPE.
I don't know what to do about this one.
-
11. Re: RESTEASY-1008: Collision between CDI and Bean Validation
ron_sigal Mar 30, 2014 8:22 PM (in response to ron_sigal)I've reorganized the solution, putting validation in org.jboss.resteasy.cdi.JaxrsInjectionTarget in the resteasy-cdi module, which avoids some problems with using interceptors when the JAX-RS resource is a session bean. All of my tests are passing now.
Jozef, thank you for your help.