Hi Marten
Thank you for replying.
By namespace, are you referring to the cache namespace configuration? (see code insert)
Code:
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="false" mode="proxy" order="2"/>
I am not using the namespace for method validation, instead i am using the bean post processor...
Code:
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
I also tried subclassing the MethodValidationPostProcessor and overriding the getOrder method amongst other things to return a lower (configurable) number than the caching namespace order configuration. This resulted in the following configuration and code.
Code:
<bean class="org.jjvester.spring.validation.InventoryMethodValidationPostProcessor">
<property name="order" value="1"></property>
</bean>
public final class InventoryMethodValidationPostProcessor extends MethodValidationPostProcessor {
private static final long serialVersionUID = 1L;
private int order;
/**
* {@inheritDoc}
*/
@Override
public int getOrder() {
return order;
}
/**
* Sets the order.
*
* @param order the new <code>order</code>
*/
public void setOrder(final int order) {
this.order = order;
}
}
This is the first time i have needed to override a packaged PostProcessor so not sure if this will work the way i am hoping.
Unfortunately, even though the InventoryMethodValidationPostProcessor does load it appears as though i have the same problem where the SPEL expression is being evaluated before the validation prompting me to think that the cache advice still seems to fire before the validation advice.
The following partial stacktrace can be observed when enabling caching and validation on the same joinPoint.
Code:
org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 9): Field or property 'sku' cannot be found on null
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:205)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:72)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:93)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:88)
at org.springframework.cache.interceptor.ExpressionEvaluator.key(ExpressionEvaluator.java:80)
at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:464)
at org.springframework.cache.interceptor.CacheAspectSupport.inspectCacheables(CacheAspectSupport.java:291)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:198)
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy31.save(Unknown Source)
at org.jjvester.inventory.IntegrationInventoryServiceValidationTest.testSaveNullProduct(IntegrationInventoryServiceValidationTest.java:20)
One can clearly see the CacheAspectSupport firing and the resultant SPEL exception
Conversely if I disable caching and only enable validation the result is somewhat expected.
Code:
org.hibernate.validator.method.MethodConstraintViolationException: The following constraint violations occurred: [MethodConstraintViolationImpl [method=public abstract org.jjvester.shared.inventory.ProductVO org.jjvester.inventory.InventoryService.save(org.jjvester.shared.inventory.ProductVO), parameterIndex=0, parameterName=arg0, kind=PARAMETER, message=Product required., messageTemplate=Product required., rootBean=org.jjvester.inventory.Inventory@360d50a6, rootBeanClass=class org.jjvester.inventory.Inventory, leafBean=org.jjvester.inventory.Inventory@360d50a6, invalidValue=null, propertyPath=InventoryService#save(arg0), constraintDescriptor=ConstraintDescriptorImpl{annotation=javax.validation.constraints.NotNull, payloads=[], hasComposingConstraints=true, isReportAsSingleInvalidConstraint=false, elementType=PARAMETER, definedOn=DEFINED_IN_HIERARCHY, groups=[interface javax.validation.groups.Default, interface org.jjvester.inventory.InventoryService], attributes={message=Product required., payload=[Ljava.lang.Class;@191e31ea, groups=[Ljava.lang.Class;@d5f0688}}]]
at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy31.save(Unknown Source)
at org.jjvester.inventory.IntegrationInventoryServiceValidationTest.testSaveNullProduct(IntegrationInventoryServiceValidationTest.java:20)
being a bit rusty with Spring of late and new to these features i would not dismiss the obvious silly oversight
Just a pity i have no idea what that is
lol