Is JSR-303 also intended for method parameter validation?
If so, is there any example on the web? The biggest challenge I'm facing is how to get a validator within each method. With Spring 3, doesn't it mean that I'd have to inject virtually every class with a LocalValidatorFactoryBean?
Thanks!
Method level validation will be supported in the upcoming version 4.2 of JSR 303's reference implementation Hibernate Validator.
As pointed out in the previous answer this will allow constraint annotations (built-in as well as custom defined types) to be specified at method parameters and return values to specify pre- and post-conditions for a method's invocation.
Note that HV will only deal with the actual validation of method calls not with triggering such a validation. Validation invocation could be done using AOP or other method interception facilities such as JDK's dynamic proxies.
The JIRA issue for this is HV-347 [1], so you might want to add yourself as watcher to this issue.
[1] http://opensource.atlassian.com/projects/hibernate/browse/HV-347
The javadocs for each of the JSR 303 annotations tells the following:
#Target(value={METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER})
See, PARAMETER is there. So, yes, it's technically possible.
Here's an example:
public void method(#NotNull String parameter) {
// ...
}
I'm however not sure how that integrates with Spring since I don't use it. You could just give it a try.
In Spring 3.1.0 you can use #Validated annotation to activate validation on a pojo.
Create an interface for the pojo class an put this annotation over it, then add your validation annotations in the methods definitions. ( the interface is required because Spring will create a proxy class using the interface as definition )
#Validated
public interface PojoClass {
public #NotNull String doSomething(#NotEmpty String input);
}
your pojo :
public class PojoClassImpl implements PojoClass {
public String doSomething(String input) {
return "";
}
}
Starting from a standard spring web application with active validation, remember to add in your spring configuration this bean declaration:
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
This sounds like a use case for AOP (AspectJ). Write a pointcut for methods that are annotated with javax.validation.constraints.*, inject a validator into the aspect (probably using Spring) and use a #Before or #Around advice to perform the validation before method execution.
Read AspectJ in Action for reference.
You can use jcabi-aspects (I'm a developer), which integrates JSR 303 with AspectJ. Actual validation is done by one of JSR 303 implementations, which you will have to add to class path, like Hibernate Validator, or Apache BVal.
Related
I want to define a annotation like #PlatformRelated, once it is marked in a interface, there will be a proxy bean at spring context, and this proxy bean should be #Priority.I want this proxy could invoke different implement according to key parameter #KeyPrameter.And I still wanna use spring features like #Async,#Trasaction,etc... at my Implement1 and Implement2.
#PlatformRelated
interface MyInterface {
method(#KeyPrameter String parameter);
}
#Component
class Implement1 implements MyInterface {
method(String parameter){
//do something 111
}
}
#Component
class Implement2 implements MyInterface {
method(String parameter){
//do something 222
}
}
#Service
class BusinessService{
#Autowired
private MyInterface myInterface;
public void doSomething() {
myInterface.method("key1");
//Implement1 work
myInterface.method("key2");
//Implement2 work
}
}
Do you guys have some good idea to complete it?
I must admit I haven't totally understood the meaning #Priority, however, I can say that if you want to implement this feature in spring, you should probably take a look at Bean Post Processors.
BeanPostProcessors are essentially a hook to Bean Creation process in spring intended for altering bean behavior.
Among other things, they allow wrapping the underlying bean into the proxy (CGLIB/java.lang.Proxy if you're working with interfaces, or even using programmatically Spring AOP), these proxies can provide a hook to the method execution that can read your annotations (like mentioned #KeyParameter) and execute a code in a way similar to Aspect's code that you already make use of.
Not all bean post processor wrap the bean into the proxy. For example, if you want to implement a BPP that uses "#Autowire", you will return the same bean, just "inject" (read, put by reflection) its dependencies. On the other hand, if you want to implement with BPP #Transactional behavior, then yes, you should wrap the bean into a proxy that would take care of transaction management capabilities before and after the method execution.
It's totally ok to have a spring bean that gets "altered" by many post processors, some of them would wrap it into a proxy other will just modify-and-return the same bean, If there are many BPP-s that wrap the bean into proxy we'll get "proxy inside proxy inside proxy" (you get the idea). Each layer of proxy will handle one specific behavior.
As an example, I suggest you take a look at existing Spring postprocessors, or, for instance, a source code of the following library: Spring Boot metering integration library
This library contains some implementations of post processors that allow metrics infrastructure integration by defining annotations on methods of Spring Beans.
I have a collection of classes which I want to be injected into the Spring application context. However, these classes can only be guaranteed to be annotated with one of a group of annotations I have written - i.e. I can assume it will be annotated with #MyAnnotation, but not #Component.
However, #MyAnnotation forms part of an API for my project, and I don't want to state an explicit dependency of this API on Spring. Thus, I can't annotate #MyAnnotation with #Component in order to have it be transitively picked up by Spring.
Is there a way to tell Spring to additionally include #MyAnnotation in its classpath scanning without adding this dependency to my API?
Currently I'm manipulating the bean definition registry to 'manually' add each class annotated with #MyAnnotation, but I'd prefer to rely on Spring's inbuilt support.
Thanks in advance.
It's possible if you create your own BeanDefinitionRegistryPostProcessor to register your own beans. If you implement the postProcessBeanDefinitionRegistry method, you can add beans to the registry by yourself, for example:
#Component
public class FooFactoryBean implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registry.registerBeanDefinition(..);
}
}
To obtain these bean definitions, you can use the ClassPathScanningCandidateComponentProvider class, which will create BeanDefinition objects for all classes found for a specific filter. In this case, an AnnotationTypeFilter will work:
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(Foo.class));
Set<BeanDefinition> definitions = scanner.findCandidateComponents("com.example.my");
In this example, it will find all classes annotated with #Foo in the com.example.my package.
#Configuration classes and XML based configuration should work for you. Have a look at this tutorial: https://www.tutorialspoint.com/spring/spring_java_based_configuration.htm
But to get your #MyAnnotations picked up is more difficult (see #g00glen00b's answer), and I'm not sure it makes sense if the above mentioned solutions are available.
Is it possible to use #DeclareMixin with Spring AOP? Or do they only support #DeclareParents?
I want to write an aspect that mixes in the java.beans.PropertyChangeSupport into a java bean:
public class PropertyChangeSupportWithInterface extends PropertyChangeSupport
implements IObservableBean {
public PropertyChangeSupportWithInterface(Object sourceBean) {
super(sourceBean);
}
}
(IObservableBean simply contains all public methods from the PropertyChangeSupport)
#Aspect
#Named
public class ObservableAspect{
#DeclareMixin("#ObservableBean *")
public static IObservableBean createDelegate(Object object) {
return new PropertyChangeSupportWithInterface(object);
}
}
It seems that this aspect is never used, which makes me think that the #DeclareMixin is not supported by the runtime weaving done by Spring AOP.
Is there any way to get this working with Spring AOP?
You can find a (not) running example here (Maven multi module project):
https://github.com/BernhardBln/SpringAOPObservableBean
See the (only) test case in the springaop-observable-bean-aspect submodule.
No, it's not supported by Spring AOP out the box. I see two options:
Create a DeclareMixinIntroductionInterceptor for Spring AOP.
Switch to Aspectj
I think that PropertyChange interface fits better in Aspectj because usually you will create a lot of proxies for prototype beans and them could be created easily out of the framework, by an ORM for example.
Edit
However I'm interested in this feature too and I already done some work for use it:
A DelegateFactoryIntroductionInterceptor to support creating delegates from the aspect instance.
A DeclareMixinAdvisor to join the inteceptor with the type pattern.
A DeclareMixinAspectJAdvisorFactory to support the DeclareMixin annotation.
To use it you only need to declare a bean of type DeclareMixinAutoProxyCreatorConfigurer
for configuring the AnnotationAwareAspectJAutoProxyCreator with the AdvisorFactory above.
I'm just testing, but seem that work fine.
Consider a bit of Groovy code like:
def trainingCorpus = new CorpusNexmlReader(ignoreMissingTags: true,
model: model, source: corpus,
abideByUse: true, useListSource: true,
listSourceDir: corpus + "/all/",
listSource: corpus + "/all/split_all.txt",
tagMap: tagMap
)
This helpfully uses the no-args constructor to make the object, and then makes calls
to all the setters corresponding to the named parameters. Now, if I add an #PostConstruct,
will Groovy call it after all those setters?
No, it won't. The #PostConstruct is used only for spring beans (instantiated by the spring context, and not by you)
From the javadocs on the #PostConstruct annotation:
"The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization. This method MUST be invoked before the class is put into service. This annotation MUST be supported on all classes that support dependency injection"
Groovy is not a dependency injection framework. It will not do any processing of annotations directed toward DI frameworks. If you were building your bean as a Spring bean using Groovy's spring builder, then it should respect that annotation.
Alternately, you could read and process that annotation yourself.
I'm working with an older spring project that's using the SimpleFormController. It was easy to switch in the beanvalidation.LocalValidatorFactoryBean validator bean to look at the annotations on the command object, but I can't see how I would override one of the methods to enable the validator to look at a specified group of validation rules. Any ideas?
You could conceivably write a spring Validator which thinly wraps the javax.validation.Validator, which would allow you to call the rules you would like; and just inject this into the controller.