Thanks to this question, I think I understand how validation is working.
As for JPA, here we have a specification called JSR-303 explaining how Bean Validation should work and then we are using implementations like the commonly used Hibernate Validator or Apache BVal also.
I am struggling about using #Validin some part of my code. I am not using #Validated because I do not need group validation.
You can find an example of a demo project here
In PropertyExample class, you can see I marked my class for bean validation to happen.
When using #Validated, everything work as expected since I am violating a constraint in my application.yml file.
When using #Valid over #Validated, it seems nothing happens. I do not understand why.
I saw too that those annotations could be used on ElementType.PARAMETER but when I am using using them during constructor initialisation, validation doesn't seem to trigger either.
Explanations on how to used those annotations (especially the #Valid) would be greatly appreciated.
It works when using Validated and doesn't when using Valid simply because Spring Boot requires properties classes to be annotated with Validated if you want them to be validated. See the documentation:
Spring Boot attempts to validate #ConfigurationProperties classes whenever they are annotated with Spring’s #Validated annotation
[...]
You can also trigger validation by annotating the #Bean method that creates the configuration properties with #Validated.
Note that they can't possibly allow the use of Valid on properties classes, since the Valid annotation isn't applicable to classes.
Related
I am using a dependency JAR in my project which has a custom annotation "#monitor"
This annotation is being used at a lot of places in the code.
Going forward, I would like to perform a quick test if there are any performance improvements if we ignore this annotation(As there are reflection api calls due to this).
I do not want to remove annotation classes from the dependency JAR as other projects might be using this. I also do not want to go to every method in my code or inside JAR to remove the "#monitor" annotation from methods.
Is there a way in SpringBoot2 to ignore a particular annotation from a spring configuration class?
Is there a way in SpringBoot2 to ignore a particular annotation.
I want to see the internal working of Java's and Spring's annotation
Like how #Controller, #RequestMapping("/") and all mapped inside, so I want to see Spring's Annotation Processor's Implementations.
Also same for #Override and other Java's Annotation Processor.
When I want to see the implementation or where it is used, I usually use IntelliJ IDEA search usages feature.
Example for your specific request, I searched in all files after the imports
import org.springframework.web.bind.annotation.RequestMapping
You can use also the show usages feature, but you will you will need to configure it to skip comments to avoid noise.
While fixing all the deprecated api's when upgrading to Spring 4.3.3, I'm facing an issue with the MultiActionController class which is used in multiple locations.
Are there any alternative classes in spring which have the same functionality as MultiActionController?
As per the spring docs:
as of 4.3, in favor of annotation-driven handler methods ,we need to
follow annotation .
Are annotations the only solution or are there any other classes or workarounds?
As far as I'm aware, annotations are the only way now, unless you're willing to use the deprecated MultiActionController class.
In the javadoc for the MultiActionController class, they state that it's deprecated in favor of annotations, so logically there should be an annotation to replace (or at least mimic) the majority on methods within the class. They don't list any other alternatives or workarounds so I doubt there are any. The methods don't specify anything either.
Here is the Spring 4.3.3 framework reference which could aid you in tracking down the annotations you're looking for. Section 30.6 - Annotation-driven listener endpoints would be a good place to start.
Here is a page on Migrating to spring framework 4.x, and finally, a page on Converting a Spring Controller into a #Controller. These links should point you in the right direction.
I need to look up beans via their class type. When the beans have been wrapped by a Proxy (some methods are #Transactional) - the ApplicatoinContext fails to find them. I find that if I look them up via an interface, it works but in this case I'm working with a concrete class type. I know the bean is of the type I'm looking for but the getBean() method fails.
I can debug (and fix) the problem in Spring's AbstractBeanFactory code. The issue is that it checks the type of the beanInstance against type I'm requesting but the beanInstance.getClass() is a Proxy. AbstractBeanFactory should compensate for this and compare the type to the proxy's target class.
I have a fix for this but I don't particularly want to use a patched version of Spring and I suspect there must be something I can configure to get this working, or is this really a bug?
There are two major ways Spring implements AOP (e.g. #Transactional support): either by using proxy interfaces or CGLIB.
With interfaces (default) if your class implements any interfaces, Spring will create a proxy implementing all that interfaces. From now on you can only work with your bean through that interfaces. Your class is deeply burried inside them.
If you enable proxying target classes instead via cglib:
<aop:config proxy-target-class="true">
Spring will create a subclass (obvoiusly still implementing all your interfaces) instead. This will fix your problem. However remember that the returned object is not really your class but dynamically generated subclass that wraps and delegates to your original object. This shouldn't be a problem in most of the cases.
And no, of course this is not a bug but well known behaviour and no, there is no need to patch Spring.
See also
Location of the proxy class generated by Spring AOP
Getting Spring Error "Bean named 'x' must be of type [y], but was actually of type [$Proxy]" in Jenkins
How to mix CGLIB and JDK proxies in Spring configuration files?
Mocking a property of a CGLIB proxied service not working
<context:component-scan base-package="<Your base package name goes here>" />
<aop:aspectj-autoproxy />
<aop:config proxy-target-class="true"/>
write these three lines in applicationContext.xml this worked for me.
According to the Spring docs, to enable autodetection of annotated controllers, you add component scanning to your configuration:
<context:component-scan base-package="org.springframework.samples.petclinic.web"/>
My question is, why is this necessary?
If a Controller has an annotation to already indicate what it is, shouldn't that be enough for Spring without component scanning?
How else would Spring find the classes? If you haven't told Spring to look in a certain class or package, those classes aren't going to get loaded, and Spring is never going to find them.
This is more a limitation of the java classloading model (if you can call it a limitation), then it is a limitation of Spring.
You only have to put the following in your configuration:
<context:annotation-config/>
If you only put the annotation on your class, the framework had to load all the classes to check if the annotation is present.
To minimize this overhead, you have to put the annotation-config tag in your configuration. That way the framework knows it has to check the classes from that configuration.
You can help the framework by specifying the package where your annotated classes are with the "base-package" attribute.
//EDIT//
This also explains the note in the documentation:
Note
<context:annotation-config/> only
looks for annotations on beans in the
same application context in which it
is defined. This means that, if you
put in a
WebApplicationContext for a
DispatcherServlet, it only checks for
#Autowired beans in your controllers,
and not your services.
Simply annotating a class with #Controller doesn't necessarily mean you want it to be part of your Spring context. Imagine if the class is part of another application, or part of a third party library, or a deprecated component of your system, etc. Just because it is on the classpath doesn't necessarily mean that you want it automatically instantiated as a bean in your Spring context.