Spring Boot : how auto configure works and #JsonTest - spring-boot

I've read some stuff about how auto-configuration works behind the scene (configuration classes with #Conditional, spring.factories inside /META-INF etc...)
Now I'm trying to understand with an example : #JsonTest
I can see this annotation is annotated with things like #AutoConfigureJson
What this #AutoConfigureJson does exactly ? Does it import some configuration classes with beans inside ? How Spring know how to use this annotation (basically this annotation is almost empty and doesn't say which classes to scan)

#AutoConfigure... (like #AutoConfigureJson) annotations are the way to allow tests with multiple "slices".
Slices load into your tests only a subset of the application, making them run faster. Let's say you need to test a component that uses the Jackson Object Mapper, then you would need the #JsonTest slice. (here is the list of all available slices.)
But you may also need some other part of the framework in your test not just tha single slice; let's say the JPA layer. You may want to annotate the test with both #JsonTest and #DataJpaTest to load both slices. According to the docs, this is not supported.
What you should do instead is choose one of the#...Test annotation, and include the other with an #AutoConfigure... annotation.
#JsonTest
#AutoConfigureDataJpa
class MyTests {
// tests
}
Update:
at a certain point while evaluating the annotation, Spring Boot will hit this line and will pass to the method SpringFactoriesLoader.loadFactoryNames() a source, that is the fully qualified name of the annotation (like interface org.springframework.boot.test.autoconfigure.json.AutoConfigureJson for example).
The loadFactoryNames method will do its magic and read the necessary information from here.
If more details are needed, the best thing is to use a debugger and just follow along all the steps.

Related

Spring finds a test class on a jar and I get a NoUniqueBeanDefinitionException

I have a project that uses Spring. The project consists on two different parts, the generic part and the specific one. The generic part is compiled as a .jar, it defines a set of traits and it's used as a dependency by the specific part, which is the one that implements the methods.
In order to test the generic part, I have created a "fake" implementation of one of the trait (let's say "fakeMethodA"), under the test directory of the generic project and I annotated this fake implementation with the #Component annotation. I'm getting the beans using the application context.
The problem comes when I try to use this generic part on the specific project. Since my actual implementation of this trait (let's say "methodAImplementation") also has a #Component annotation, when I run my tests I get:
org.springframework.beans.factory.NoUniqueBeanDefinitionException
expected single matching bean but found 2:
It finds the fakeMethodA from the generic part and methodAImplementation from the implementation. Is there any way to exclude this "fake" implementation from the execution? Is there a better way to define this?
Any help would be greatly appreciated.
The problem was solved by the use of #Profile annotation on the generic method.
I annotated the fake method on the tests with:
#Profile(value = Array("Test"))
And the right implementation with another profile value. After that, when I select the bean from the context, I can select the correct profile.

How to use AOP annotation inside method not in method level

I am using Spring AOP to log the DB execution time, but it is applying to the entire method execution time.
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface TrackExecutionTime {
}
Is there any possibility that we can use this #TrackExecutionTime not in the method level but inside a method just above some statement like below -
#TrackExecutionTime
List<Release> releaseList = releaseRepo.findByProductName(productName.toUpperCase());
that way I can able to get only the DB execution time not only the entire method execution time, as my method contains other business logic too which also including if we use the AOP annotation at the method level.
Your question is not AOP-specific, because annotations are a Java language feature. The answer is: Annotations on arbitrary lines of code are not part of the Java language concept, which for you means you also cannot use them for AOP purposes. This is simply a Java limitation. Neither Spring AOP nor native AspectJ can support a feature which does not exist in Java to begin with.
Friendly suggestion: Please learn more about Java first, then get acquainted with some basic software design and clean code principles. Finally, you shall be able to achieve what you want, albeit in a different way from what you just dreamed up here.
Spring AOP default configuration uses proxies to execute the aspect hence only methods can be annotated.
A bit of a detour on the proxies. A proxy wraps a target method so when you call a method elsewhere Spring makes sure to invoke the method on the proxy and that invocation then contains the aspect code which gets executed before, after, around the call itself (depending on the aspect). There can be several proxies wrapping a single class.
Then an option is to add your aspect annotation to the repository method.
If we need to track the execution time only for subset of calls to the method (which sounds a bit strange a requirement) then we can add a wrapper method - say make a Spring-managed Metrics class with a said time tracking method that accepts a lambda and is annotated with the #TrackExecutionTime. The original call would then be something like
metrics.executeTimed(() -> releaseRepo.findByProductName(productName.toUpperCase()));

Initialise autowired service in spring boot

I am running 100 JUnit tests with a single autowired service. I have a service named createArray this service adds values in the ArrayList.
The problem is the values persist in the array list. When a new test case runs it adds its own value to the array.
I want to clear the autowired creatArray object whenever new test case runs.
Spring beans by default are singleton, this is why this is happening.
In order to have a different behaviour you should check the different "bean scope".
This is a quick explanation of it:
https://www.tutorialspoint.com/spring/spring_bean_scopes.htm
I believe that if you use the prototype scope ( as per this tutorial ) you might end up with the solution you want.
Regarding how to do this, it really depends if your beans are defined by xml or annotation.
You can check google a lot of examples.
In case you using XML it should be easy, on the bean add the "scope=prototype".
For annotation use under #Bean the annotation #Scope("prototype")

Spring Weaving: #Configurable objects do not get woven correctly if used as a Parameter inside Methods of Autoproxies

Please consider following situation with spring 4.0.7
For Eclipselink, we use a load-time-weaver. So we wanted to experiment with Springs #Configurable annotation using #EnableSpringConfigured with #EnableLoadTimeWeaving at the same time.
This is fully functional, and Spring-Beans are injected perfectly into POJOs during construction. This functionality is helpful for us, because we want to keep some code regarding validation of these POJOs inside these and not somewhere else in a Bean.
SOme of our Spring Context contains Beans that do not implement any interface, because they are local to some package and used only there. Lets say, FooLogicBean is one of them. If this is to be injected into another Bean, and some Spring-AOP-Aspect (not-aspectj) like some performance measurement aspect is in the execution path, Spring will create a CGLIB autoproxy for the FooLogicBean and inject that. This is fully functional and works perfectly too.
Problems arise, when we want to actually use a POJO that is annotated with #Configurable as a parameter in a method of FooLogicBean (like fooLogicBean.doValidate(myPojo); ), respectively a CGLIB Proxy. In this case, some non-trivial magic stops that POJO from being woven thru aspectj (AnnotationBeanConfigurerAspect from spring-aspects). It is even never woven anywhere in the code regardless of calling the aforementioned doValidate() Method.
If we create that POJO inside FooLogicBean, but dont use it as a method Parameter, it gets woven again due to #Configurable.
Without knowing the Autoproxy creation code, we assume some fancy marking routine from hindering a class from being detected by aspectj, if that class was already used in spring-aop. use in this case means Access.
Did anyone experiment with such obscure constellation and knows a solution for that?
Thanks in advance!
Proxies are created by subclassing, i.e. when you create a proxy of an annotated class Foo:
class Foo {
#Bar
void bar() { }
}
the proxy is created by implementing a class
class Foo$Proxy extends Foo {
#Override
void bar() {
// Proxy logic
}
// Overridden methods of Object
}
This makes the Foo$Proxy class a valid Liskov substitute for Foo. However, normal override semantics apply, i.e. non-inherited annotations such as #Bar are not longer present for the overridden methods. Once another annotation-based API processes your beans, all annotations have disappeared which leads to your outcome. This is true for all kinds of annotations. Those on types, methods and method parameters.
But is it avoidable? It most certainly is by using a proxy generator that was written recently and is built with knowledge of what annotations are, something that is not true for cglib which was first shipped in the early days of the Java virtual machine. However, as long as Spring does not move away from cglib, you will have to live with today's limitations.

Why to use #Autowired on class in Spring

I read about the advantages of using Dependency for interface.
I understand the concept for interface - but why to use #Autowire on class? If we use Autowire on class I know in advance what is the implmeneted class and it's like a regular member of it (without the ability of get to this member)!
What am I missing?
1) Convenience - you do not need to take care for initializing your components, you save time on typing code and configuration files,
2) Forcing good practices - your components to be autowired must be written to be manageable by Spring and spring will take care about error checking for you and pop all errors. So your code will be organized in component collaborating way.
3) Autowiring will also reduce your effort when your classes/beans will grow and evolve.
If you use #Autowire and not call the constructor, you mark the class to be dynamically initialized by the Spring Container. This allows you to set class properties as defined in your spring configuration.
If we use Autowire on class I know in
advance what is the implmeneted class
and it's like a regular member of it
When you wire the dependency through XML instead of Annotations, you also know in advance in which class are you going to inject it.
But You still declare an Interface as dependency, so you can wire any Implementation of this interface at runtime.

Resources