Specifying Group for Bean Validation with SimpleFormController - java

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.

Related

How to add converters when ApplicationConversionService.getSharedInstance() is no longer modifiable?

I'm in the process of upgrading spring boot from 2.4.2 to 2.5.6.
In our code we have been using ApplicationConversionService.getSharedInstance().addConverter() to add our custom converters. It puzzles me a bit that this is mentioned as a "New feature" rather than a breaking change for Spring boot 2.5.0-RC1, see the top mention here. https://github.com/spring-projects/spring-boot/releases?page=3
It was changed by this PR: https://github.com/spring-projects/spring-boot/issues/26088
How can we add the converters instead?
You need to provide the converter as a bean and annotate the bean definition with #ConfigurationPropertiesBinding. The simplest way to do so is probably to annotate the converter class with #Component and #ConfigurationPropertiesBinding.
See also this part of the reference documentation: https://docs.spring.io/spring-boot/docs/2.5.6/reference/htmlsingle/#features.external-config.typesafe-configuration-properties.conversion

What is javax.inject.Named annotation supposed to be used for?

I am trying to understand the javax.inject package and I am not clear what the javax.inject.Named annotation is supposed to be used for. The Javadoc does not explain the the idea behind it.
Javadoc is at http://download.oracle.com/javaee/6/api/javax/inject/Named.html
I am using Spring 3.0 to write some sample programs, by putting #Named on a bean it seems to add it to the bean factory but the Javadoc description is so light I can't tell if that is the standard behavior or Spring specific behavior.
My questions are:
What is the difference between #Named and #Qualifier
How are you supposed to tell the Runtime system a class should be injectable in other classes what's the annotation for that? The equivalent of #Component in Spring?
Update 1 there is an excellent explanation of #Named and #Qualifier at Nice article about #Named and #Qualifier https://dzone.com/articles/java-ee6-cdi-named-components thanks #xmedeko for linking to it the comment below.
Use #Named to differentiate between different objects of the same type bound in the same scope.
#Named("maxWaitTime")
public long maxWaitTimeMs;
#Named("minWaitTime")
public long minWaitTimeMs;
Without the #Named qualifier, the injector would not know which long to bind to which variable.
If you want to create annotations that act like #Named, use the #Qualifier annotation when creating them.
If you look at #Named, it is itself annotated with #Qualifier.
#Inject instead of Spring’s #Autowired to inject a bean.
#Named instead of Spring’s #Component to declare a bean.
Those JSR-330 standard annotations are scanned and retrieved the same way as Spring annotation (as long as the following jar is in your classpath)
Regarding #2, according to the JSR-330 spec:
This package provides dependency
injection annotations that enable
portable classes, but it leaves
external dependency configuration up
to the injector implementation.
So it's up to the provider to determine which objects are available for injection. In the case of Spring it is all Spring beans. And any class annotated with JSR-330 annotations are automatically added as Spring beans when using an AnnotationConfigApplicationContext.
The primary role of the #Named annotation is to define a bean for the purpose of resolving EL statements within the application, usually through JSF EL resolvers. Injection can be performed using names but this was not how injection in CDI was meant to work since CDI gives us a much richer way to express injection points and the beans to be injected into them.

Method Parameter Validation with JSR-303

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.

How does Wicket's #SpringBean annotation work?

How does Wicket's #SpringBean annotation work? Does it use reflection at run time? Does it make the compiler inject some code? Or what?
#SpringBean works using Wicket's underlying Injector mechanism. When you instantiate a Wicket component, the constructor of Wicket's component base class introspects the class being instantiated, looking for the #SpringBean annotation. If the bean is found, then Wicket generates a proxy for the spring bean and injects it into the component's field. This is Wicket's equivalent of Spring's #Autowired annotation, the effect is similar.
It doesn't, however, have anything to do with Spring's own context/classpath scanning functionality (e.g. #Component), which is about auto-discovery of what is and isn't a bean, rather having anything to do with wiring.
The class marked with a #SpringBean annotation has to have one of:
A no-args constructor
A superclass with a no-args constructor
Implement an interface
An exception will be thrown if these conditions are not met as Wicket will not be able to proxy the class.
Spring uses the class loader and ASM at runtime to find all annotated classes.
You can configure where spring should search for beans:
<context:component-scan base-package="some.package.to.start.from"/>
This uses the ClassPathBeanDefinitionScanner internally which will use the PathMatchingResourcePatternResolver to find the classes and the ASM-based MetadataReader to read the annotations.

Custom Spring sterotype annotation with scope of prototype?

I created a custom sterotype #Action, and Spring has managed to detect it in the package scan I configured in the configurations.
The next step I would like to do is to tell Spring that all classes with #Action should be created with prototype, instead of Singleton.
My #Action interface is as follows:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Action {
}
I tried to mark it with #Scope("prototype") but that does not seem to help.
Is what I desire possible?
Kent
The context:component-scan can be configured with a custom scope-resolver, which implements org.springframework.context.annotation.ScopeMetadataResolver.
I created a custom scope-resolver that not only checks the bean for a #Scope annotation (with the default resolver of org.springframework.context.annotation.AnnotationScopeMetadataResolver), but looks up annotations of annotations too (recursively).
One thing to note though, that looking up annotations recursively might go into an endless loop, as java.lang.annotation.Documented is annotated with java.lang.annotation.Documented. Best to maintain a table that indicates which annotation has been looked up already.
Unfortunately not with spring 2.5.X. Your #Component-annotation describes the role of the bean while the scope is a separate axis, so a role and scope descriptor typically have to be applied separately to the implementation class. When viewed in this way it makes some sense (edit: at least it did so for a few seconds, anyway)
I don't know how this will change i spring 3.x, which is not too far away. There seems to be some room for improvement.

Categories