[
https://issues.apache.org/jira/browse/OPENEJB-1525?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13025356#comment-13025356
]
Romain Manni-Bucau commented on OPENEJB-1525:
---------------------------------------------
To allow usage of hibernate-validator for this purpose the interceptor has to
be modified like this:
{code}
package org.apache.openejb.bval;
import org.apache.bval.jsr303.extensions.MethodValidator;
import org.apache.openejb.core.ivm.naming.NamingException;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import javax.annotation.Resource;
import javax.ejb.EJBException;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.naming.InitialContext;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import javax.validation.Validator;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Set;
/**
* A simple interceptor to validate parameters and returned value using
* bean validation spec. It doesn't use group for now.
*
* It is dependent of the Apache Bean Validation implementation.
*
* @author Romain Manni-Bucau
*/
public class BeanValidationAppendixInterceptor {
private static final Logger logger =
Logger.getInstance(LogCategory.OPENEJB,
BeanValidationAppendixInterceptor.class);
private static final Class<?> APACHE_BVAL_METHOD_CLASS = initApache();
private static final Class<?> HIBERNATE_METHOD_CLASS = initHibernate();
@AroundInvoke public Object aroundInvoke(final InvocationContext
ejbContext) throws Exception {
Object validatorObject = null;
Validator validator = null;
try {
validator = (Validator) new
InitialContext().lookup("java:comp/Validator");
} catch (NamingException ne) {
// no-op
}
Set<?> violations = Collections.emptySet();
if (APACHE_BVAL_METHOD_CLASS != null && validator != null) {
validatorObject = validator.unwrap(APACHE_BVAL_METHOD_CLASS);
violations = call(Set.class, validatorObject, "validateParameters",
new Object[]{
ejbContext.getTarget().getClass(), ejbContext.getMethod(),
ejbContext.getParameters(), new Class[0]
},
new Class<?>[]{
Class.class, Method.class, Object[].class, Class[].class
});
} else if (HIBERNATE_METHOD_CLASS != null && validator != null) {
validatorObject = validator.unwrap(HIBERNATE_METHOD_CLASS);
violations = call(Set.class, validatorObject,
"validateAllParameters",
new Object[]{
ejbContext.getTarget(), ejbContext.getMethod(),
ejbContext.getParameters(), new Class[0]
},
new Class<?>[]{
Object.class, Method.class, Object[].class, Class[].class
});
} else { // a warning message to inform Apache Bean Validation is not
present
if (validator == null) {
logger.error("can't find validator");
} else {
logger.warning("Apache Bean Validation is not present, "
+ BeanValidationAppendixInterceptor.class.getName() + "
will not work. "
+ "Please put it if you want to validate your parameters
and returned values "
+ "with bean validation JSR.");
}
}
if (violations.size() > 0) {
throw buildValidationException((Set<ConstraintViolation<?>>)
violations);
}
Object returnedValue = ejbContext.proceed();
violations = Collections.emptySet();
if (validatorObject != null && APACHE_BVAL_METHOD_CLASS != null) {
violations = call(Set.class, validatorObject,
"validateReturnedValue",
new Object[]{
ejbContext.getTarget().getClass(), ejbContext.getMethod(),
returnedValue, new Class[0]
},
new Class<?>[]{
Class.class, Method.class, Object.class, Class[].class
});
} else if (validatorObject != null && HIBERNATE_METHOD_CLASS != null) {
violations = call(Set.class, validatorObject, "validateReturnValue",
new Object[]{
ejbContext.getTarget(), ejbContext.getMethod(),
returnedValue, new Class[0]
},
new Class<?>[]{
Object.class, Method.class, Object.class, Class[].class
});
}
if (violations.size() > 0) {
throw buildValidationException((Set<ConstraintViolation<?>>)
violations);
}
return returnedValue;
}
// just a simple EJBException for now
private RuntimeException
buildValidationException(Set<ConstraintViolation<?>> violations) {
return new ConstraintViolationException(violations);
}
private static <T> T call(Class<T> returnedType, Object o, String
methodName, Object[] params, Class<?>[] types) {
Method method = null;
boolean accessible = true;
try {
method = o.getClass().getMethod(methodName, types);
accessible = method.isAccessible();
if (!accessible) {
accessible = false;
method.setAccessible(true);
}
return (T) method.invoke(o, params);
} catch (Exception e) {
e.printStackTrace();
throw new ValidationException("can't call method " + methodName + "
on " + o, e);
} finally {
if (method != null) {
method.setAccessible(accessible);
}
}
}
private static ClassLoader getClassLaoder() {
ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader =
BeanValidationAppendixInterceptor.class.getClassLoader();
}
return classLoader;
}
private static Class<?> initApache() {
try {
return
getClassLaoder().loadClass("org.apache.bval.jsr303.extensions.MethodValidator");
} catch (ClassNotFoundException e) {
return null;
}
}
private static Class<?> initHibernate() {
ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader =
BeanValidationAppendixInterceptor.class.getClassLoader();
}
try {
return
getClassLaoder().loadClass("org.hibernate.validator.method.MethodValidator");
} catch (ClassNotFoundException e) {
return null;
}
}
}
{code}
Note: hibernate validator only allows constraints on root interface whereas
apache bean validation needs it on child class.
> bean validation for parameters and returned values
> --------------------------------------------------
>
> Key: OPENEJB-1525
> URL: https://issues.apache.org/jira/browse/OPENEJB-1525
> Project: OpenEJB
> Issue Type: New Feature
> Components: general
> Affects Versions: (trunk/openejb3)
> Reporter: Romain Manni-Bucau
> Priority: Minor
> Attachments: bean_validation_appendix_4.0.0_r1094584.patch
>
>
> Apache bean validation implemented the appendix of the bean validation spec
> allowing to validate with bean validation annotations method parameters and
> method returned values.
> It could be pretty cool to add an interceptor to activate it.
> It should be possible as a "general interceptor" (system interceptor
> probably).
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira