#ActiveProfiles in meta annotation and on test class not working - spring

I created a meta annotation #EmbeddedMongoDBUnitTest that activates two profiles to be used in spring based unit tests. The basic setup works:
#Documented
#Inherited
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
#ActiveProfiles({"embeddedMongoDB", "embeddedMongoDBUnitTest"})
public #interface EmbeddedMongoDBUnitTest {
}
#RunWith(SpringJUnit4ClassRunner.class)
#EmbeddedMongoDBUnitTest
#ContextConfiguration(...)
public class WorkingTest {
...
}
Now when trying to activate another profile with another #ActiveProfiles annotation on the test class itself, the profiles in #EmbeddedMongoDBUnitTest aren't activated anymore:
#RunWith(SpringJUnit4ClassRunner.class)
#EmbeddedMongoDBUnitTest
#ActiveProfiles({"h2IntegrationTests"})
#ContextConfiguration(...)
public class NotWorkingTest {
...
}
Is there a reason why this is not working or is this a bug in the spring test code?

This is not a bug: this is by design.
The reason this does not work is that this form of configuration is simply not supported by Spring.
The algorithm that the Spring Framework uses when searching for an annotation stops once it has found the first occurrence of the sought annotation. Thus, in your example, the #ActiveProfiles annotation on NotWorkingTest effectively shadows the #ActiveProfiles annotation on your composed #EmbeddedMongoDBUnitTest annotation.
Please note that these are the general semantics for annotations in the core Spring Framework. In other words, the behavior you are experiencing is not specific to the spring-test module.
Having said that, profiles declared via #ActiveProfiles are in fact inherited within a test class hierarchy (unless you set the inheritProfiles flag to false). But don't confuse class hierarchies with annotation hierarchies: Java supports inheritance for interfaces and classes but not for annotations.
Hope this clarifies things!
Sam (component lead for the spring-test module)

Related

Sping-boot configuration-properties and service layer injection

I'm new to spring dependency-injection and am reaching out to learn about best practices. I would like to know if its a good design philosophy to inject classes annotated with #ConfigurationProperties into service layer classes (annotated with #Service). Im trying to map properties in my application.yml to a config-class as follows -
#ConstructorBinding
#ConfigurationProperties(prefix = "application")
class ApplicationConfig(
val kafka: someDeeplyNestedType = SomeDeeplyNestedObj()
) {
// helper functions
}
I'm then injecting above config class in service layer as follows -
#Service
#EnableConfigurationProperties(ApplicationConfig::class)
class RestService(val config: ApplicationConfig) {
init {
// Reference config object
// Reference application.yml properties via config object.
}
}
I'm curious to know if I can improve upon my current implementation - not sure if its agreeable to pass configuration classes to service-layer classes. I'm also curious to know if theres any better approach to wiring ApplicationConfig without needing to use EnableConfigurationProperties annotation.
It is agreeable, documented, and probably "unrivaled" (only bounded by: "limitations" (no SpEL -> helper functions!?;)).
To work with #ConfigurationProperties beans, you can inject them in the same way as any other bean, as shown in the following example:
#Service
public class MyService {
private final SomeProperties properties;
...
The only problems can arise from the "deeply", not "owning" the (config) structure ...and possibliy from "helper functions".
But
The prefix = "application" "sounds" suspicious!
Note:
[Most - almost All] (official) spring* boot properties, are already "typesafe", and have their object/class representation in spring-boot-autoconfigure packages.
Please study that "typesafe chapter", but also gazing at PropertySource Abstraction.
There is no hard rule for this as in Spring Boot we can add #EnableConfigurationProperties at a class level with stereotype annotations.
As a part of good practices EnableConfigurationProperties or any configuration thing should be part of Configuration class of or main spring boot class so any developer can easily figure out those configuration instead of going any specific service class and then check.
In your case, yo can use #EnableConfigurationProperties annotation in conjunction with #SpringBootApplication annotation.

How is #ConfigurationProperties-annotated classes detected automatically with #SpringBootApplication Annotation

I am learning Spring Boot and have a question with one example in the reference documentation.
Following section of the documentation mentions
6. Using the #SpringBootApplication Annotation
A single #SpringBootApplication annotation can be used to enable those
three features, that is:
#EnableAutoConfiguration: enable Spring Boot’s auto-configuration
mechanism
#ComponentScan: enable #Component scan on the package where the
application is located (see the best practices)
#Configuration: allow to register extra beans in the context or import
additional configuration classes
and the following example to replace this single annotation by any of the features that it enables is bit confusing for me . The example
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
#Configuration(proxyBeanMethods = false)
#EnableAutoConfiguration
#Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Explanation for the example
In this example, Application is just like any other Spring Boot
application except that #Component-annotated classes and
#ConfigurationProperties-annotated classes are not detected
automatically and the user-defined beans are imported explicitly (see
#Import).
The only major difference I see in the example code above is that it does not have #ComponentScan annotation. I also read in the comments section of an SO answer (Stephane Nicoll May 5 '17 at 11:07) that #Component annotation is not recommended officially to auto detect #ConfigurationProperties. So my assumption is that Spring framework classes with #ConfigurationProperties are not annotated with #Component.
Also I checked the #SpringBootApplication annotation source and couldn't identify anything that should enable the automatic detection of #ConfigurationProperties annotated classes.
The reference document 2.8.3. Enabling #ConfigurationProperties-annotated types section shows the following way to scan and autodetect #ConfigurationProperties
#SpringBootApplication
#ConfigurationPropertiesScan({ "com.example.app", "org.acme.another" })
public class MyApplication {
}
With all these details , I would like to understand
Why is it explicitly mentioned for this example that #ConfigurationProperties-annotated classes are not detected automatically ? and How is #ConfigurationProperties annotated classes automatically detected when #SpringBootApplication is used.
Additional note : I saw a small difference between the prior version of the documentation and the current one. The following reference is missing the current one
Keep in mind that the #EnableConfigurationProperties annotation is
also automatically applied to your project so that any existing bean
annotated with #ConfigurationProperties is configured from the
Environment
Following is what I understand from my analysis.
#ConfigurationProperties annotated types can be registered to the ApplicationContext by
Annotating the class with #ConfigurationProperties with an
annotation that falls in the scope of #ComponentScan (
#Component, #Service and the like ) . Not recommended as per the comment from Stephane Nicoll , which makes sense to me now.
Using annotation
#EnableConfigurationProperties . For this to
work the class annotated with #EnableConfigurationProperties
should be annotated with an annotation that falls in the scope of
#ComponentScan ( #Component, #Service and the like )
Using annotation #ConfigurationPropertiesScan and by making sure
the classes annotated with #ConfigurationProperties is placed
under its radar. The usage is similar to #ComponentScan .
Now , when we replace #SpringBootApplication with individual annotations that it enables and omit #ComponentScan (as in example) , the #EnableConfigurationProperties way (Point 2) of registering the types with #ConfigurationProperties will not work. This probably answers both my questions on why and how .
This was explicitly mentioned probably because the connection between #EnableConfigurationProperties and #ComponentScan is not that obvious for people like me.
Additional details.
The registration of #ConfigurationProperties annotated types when we use #EnableConfigurationProperties happens through of the EnableConfigurationPropertiesRegistrar class that is imported by the annotation
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Import(EnableConfigurationPropertiesRegistrar.class)
public #interface EnableConfigurationProperties {..}

How SpringBoot dependency injection works with different type of annotations

I recently started exploring Spring Boot. I see that there are 2 ways to define Beans in Spring Boot.
Define #Bean in the class annotated with #SprinBootApplication
Define #Bean in a class annotated with #Configuration
I am also confused about stereo-type annotation #Repository #Service #Controller etc.
Can someone please explain how dependency-injection works with these annotations?
Yes it is possible.
Either you use #Bean in any of your #Configuration or #SpringBootApplication class or mark the bean classes explicitly with annotations like #Service, #Component #Repository etc.
#Service or #Component
When you mark a class with #Service or #Compoenent and if spring's annotation scanning scope allows it to reach to the package, spring will register the instances of those classes as spring beans.
You can provide the packages to be included/excluded during scan with #ComponentScan
#Bean
#Beans are marked on factory methods which can create an instance of a particular class.
#Bean
public Account getAccount(){
return new DailyAccount();
}
Now in you application you can simply #Autowire Account and spring will internally call its factory method getAccount, which in turn returns an instance of DailyAccount.
There is a simple difference of using #Bean vs #Service or #Compoenent.
The first one makes your beans loosely coupled to each other.
In the #Bean, you have flexibility to change the account implementation without even changing any of the account classes.
Consider if your classes instantiation is a multi-step operation like read properties values etc then you can easily do it in your #Bean method.
#Bean also helps if you don't have source code access to the class you are trying to instantiate.
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added.
You need to opt-in to auto-configuration by adding the #EnableAutoConfiguration or #SpringBootApplication annotations to one of your #Configuration classes.
You are free to use any of the standard Spring Framework techniques to define your beans and their injected dependencies. For simplicity, we often find that using #ComponentScan (to find your beans) and using #Autowired (to do constructor injection) works well.
One way is to define #Bean in the class annotated with
#SprinBootApplication
If you see #SprinBootApplication it is combination of many annotation, and one of them is #Configuration. So when you define #Bean in the Main class, it means it's inside #Configuration class.
According to Configuration docs :
Indicates that a class declares one or more #Bean methods and may be
processed by the Spring container to generate bean definitions and
service requests for those beans at runtime.
class annotated with #Configuration
When you define #Bean is a class annotated with #Configuration class, it means it is the part of spring configuration all the Beans define in it all available for Dependency-Injection.
I have also seen some code where neither of the 2 above approaches
have been used and yet dependency injection works fine. I have tried
to research a lot on this but could not find any concrete answer to
this. Is this possible?
I am assuming you are talking about Sterio-type annotation. Every sterio type annotation has #Component, according to docs :
Indicates that an annotated class is a "component". Such classes are
considered as candidates for auto-detection when using
annotation-based configuration and classpath scanning.

What does this do: #RunWith(SpringJUnit4ClassRunner.class)

What does this annotation do?
When would I want to use it?
When would I not want to use it?
#RunWith(SpringJUnit4ClassRunner.class)
I can find more usages of this when I Google and do not find a 101 explanation as to what this annotation is supposed to communicate to me or when/why I would use it?
The annotation is used to configure a unit test that required Spring's dependency injection.
From Spring Reference - 10. Unit Testing:
10.1 Creating a Unit Test Class
In order for the unit test to run a batch job, the framework must load the job's ApplicationContext. Two annotations are used to trigger this:
#RunWith(SpringJUnit4ClassRunner.class): Indicates that the class should use Spring's JUnit facilities.
#ContextConfiguration(locations = {...}): Indicates which XML files contain the ApplicationContext.
If you are using annotations rather than XML files, then any class that you are unit testing that requires Spring dependency injection needs to be put into the #ContextConfiguration annotation. For example:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = FooManager.class)
class FooManagerTest {
#Autowired
FooManager fooManager;
Now when you use fooManager in a unit test it will have have a Spring context setup for it.
If fooManager autowires in any beans then those bean's classes also need to be in the #ContextConfiguration annotation. So if fooManager autowires in a FooReporter bean:
#ContextConfiguration(classes = {FooManager.class, FooReporter.class})
If the beans that fooManager autowires in contain state, then you will likely want to reset the state of those beans for each test. In that case you can add the #DirtiesContext annotation to your test class:
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
If fooManager or any of its autowired beans reads Spring config then you need to add an initializers list to the #ContextConfiguration annotation, that contains the ConfigFileApplicationContextInitializer class:
#ContextConfiguration(classes = {FooManager.class, FooReporter.class}, initializers = ConfigFileApplicationContextInitializer.class)
To answer the when you would and wouldn't want to use it part of the question.
When to use SpringJUnit4ClassRunner
IMO SpringJUnit4ClassRunner should be used very sparingly. There is a significant overhead involved with starting up a Spring container to run a unit test.
I typically use SpringJUnit4ClassRunner to test:
that components are injected (auto-wired) as expected
that configuration data is injected as expected
When you are injecting components issues can arise if the #Qualifier annotation is not used or used incorrectly, for example.
When loading configuration from multiple yaml files you may want to test that maps are being merged as expected, with the appropriate overrides occurring.
At the very least I always have a simple SpringJUnit4ClassRunner test as a sanity check that the Spring container starts up OK.
When not to use SpringJUnit4ClassRunner
I would not use SpringJUnit4ClassRunner to test the non-Spring related functionality in my code under test. Which in my experience means most of the functionality.
So this means that any autowired components and injected config data needs to be mocked. This can mean quite a bit of setup code for your unit tests. However this setup code only needs to be written once for all the tests in your class under test. It is also much quicker to run unit tests with mocked components.
I keep the mocking simple and use Spock to mock the components. Example groovy code:
import spock.lang.Specification
class FooManagerTest extends Specification {
FooManager cut
void createMockFooReporter() {
FooReporter mockFooReporter = Mock(FooReporter)
mockFooReporter.fooFormatter = Mock(FooFormatter)
}
void setup() {
cut = new FooManager()
cut.fooReporter = createMockFooReporter()
}
void "Basic test"() {
// Do a basic test using 'cut'
}
}
In this example the class under test FooManager has an autowired FooReporter which itself contains an autowired FooFormatter.
I think #RunWith annotation is in order to initialize the context of spring. Because the junit5 is released, you just can replace it with #SpringJUnitConfig.By the way, #RunWith annotation is already replaced by #ExtendWith, but you still can use it.

Is Spring annotation #Controller same as #Service?

Is Spring annotation #Controller same as #Service?
I have idea about #Controller which can be used for URL mapping and invoking business logic.
while #Service used to annotate service class which contains business logic.
Can I use #Controller instead of #Service to annotate Service class?
No, they are pretty different from each other.
Both are different specializations of #Component annotation (in practice, they're two different implementations of the same interface) so both can be discovered by the classpath scanning (if you declare it in your XML configuration)
#Service annotation is used in your service layer and annotates classes that perform service tasks, often you don't use it but in many case you use this annotation to represent a best practice. For example, you could directly call a DAO class to persist an object to your database but this is horrible. It is pretty good to call a service class that calls a DAO. This is a good thing to perform the separation of concerns pattern.
#Controller annotation is an annotation used in Spring MVC framework (the component of Spring Framework used to implement Web Application). The #Controller annotation indicates that a particular class serves the role of a controller. The #Controller annotation acts as a stereotype for the annotated class, indicating its role. The dispatcher scans such annotated classes for mapped methods and detects #RequestMapping annotations.
So looking at the Spring MVC architecture you have a DispatcherServlet class (that you declare in your XML configuration) that represent a front controller that dispatch all the HTTP Request towards the appropriate controller classes (annotated by #Controller). This class perform the business logic (and can call the services) by its method. These classes (or its methods) are typically annotated also with #RequestMapping annotation that specify what HTTP Request is handled by the controller and by its method.
For example:
#Controller
#RequestMapping("/appointments")
public class AppointmentsController {
private final AppointmentBook appointmentBook;
#Autowired
public AppointmentsController(AppointmentBook appointmentBook) {
this.appointmentBook = appointmentBook;
}
#RequestMapping(method = RequestMethod.GET)
public Map<String, Appointment> get() {
return appointmentBook.getAppointmentsForToday();
}
This class is a controller.
This class handles all the HTTP Request toward "/appointments" "folder" and in particular the get method is the method called to handle all the GET HTTP Request toward the folder "/appointments".
I hope that now it is more clear for you.
If you look at the definitions of #Controller, #Service annotations, then you'll find that these are special type of #Component annotation.
#Component
public #interface Service {
….
}
 
#Component
public #interface Controller {
…
}
So what's the difference?
#Controller
The #Controller annotation indicates that a particular class serves the role of a controller. The #Controller annotation acts as a stereotype for the annotated class, indicating its role.
What’s special about #Controller?
You cannot switch this annotation with any other like #Service or #Repository, even though they look same.
The dispatcher scans the classes annotated with #Controller and detects #RequestMapping annotations within them. You can only use #RequestMapping on #Controller annotated classes.
#Service
#Services hold business logic and call method in repository layer.
What’s special about #Service?
Apart from the fact that it is used to indicate that it's holding the business logic, there’s no noticeable specialty that this annotation provides, but who knows, spring may add some additional exceptional in future.
Linked answer: What's the difference between #Component, #Repository & #Service annotations in Spring?
No, #Controller is not the same as #Service, although they both are specializations of #Component, making them both candidates for discovery by classpath scanning. The #Service annotation is used in your service layer, and #Controller is for Spring MVC controllers in your presentation layer. A #Controller typically would have a URL mapping and be triggered by a web request.
#Service vs #Controller
#Service : class is a "Business Service Facade" (in the Core J2EE patterns sense), or something similar.
#Controller : Indicates that an annotated class is a "Controller" (e.g. a web controller).
----------Find Usefull notes on Major Stereotypes
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/stereotype/Component.html
#interface Component
#Target(value=TYPE)
#Retention(value=RUNTIME)
#Documented
public #interface Component
Indicates that an annotated class is a component. Such classes are considered as candidates for auto-detection when using annotation-based configuration and classpath scanning.
Other class-level annotations may be considered as identifying a component as well, typically a special kind of component: e.g. the #Repository annotation or AspectJ's #Aspect annotation.
#interface Controller
#Target(value=TYPE)
#Retention(value=RUNTIME)
#Documented
#Component
public #interface Controller
Indicates that an annotated class is a "Controller" (e.g. a web controller).
This annotation serves as a specialization of #Component, allowing for implementation classes to be autodetected through classpath scanning. It is typically used in combination with annotated handler methods based on the RequestMapping annotation.
#interface Service
#Target(value=TYPE)
#Retention(value=RUNTIME)
#Documented
#Component
public #interface Service
Indicates that an annotated class is a "Service", originally defined by Domain-Driven Design (Evans, 2003) as "an operation offered as an interface that stands alone in the model, with no encapsulated state."
May also indicate that a class is a "Business Service Facade" (in the Core J2EE patterns sense), or something similar. This annotation is a general-purpose stereotype and individual teams may narrow their semantics and use as appropriate.
This annotation serves as a specialization of #Component, allowing for implementation classes to be autodetected through classpath scanning.
#interface Repository
#Target(value=TYPE)
#Retention(value=RUNTIME)
#Documented
#Component
public #interface Repository
Indicates that an annotated class is a "Repository", originally defined by Domain-Driven Design (Evans, 2003) as "a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects".
Teams implementing traditional J2EE patterns such as "Data Access Object" may also apply this stereotype to DAO classes, though care should be taken to understand the distinction between Data Access Object and DDD-style repositories before doing so. This annotation is a general-purpose stereotype and individual teams may narrow their semantics and use as appropriate.
A class thus annotated is eligible for Spring DataAccessException translation when used in conjunction with a PersistenceExceptionTranslationPostProcessor. The annotated class is also clarified as to its role in the overall application architecture for the purpose of tooling, aspects, etc.
As of Spring 2.5, this annotation also serves as a specialization of #Component, allowing for implementation classes to be autodetected through classpath scanning.
I already answered similar question on here Here is the Link
No both are different.
#Service annotation have use for other purpose and #Controller use for other.
Actually Spring #Component, #Service, #Repository and #Controller annotations are used for automatic bean detection using classpath scan in Spring framework, but it
doesn't ,mean that all functionalities are same.
#Service: It indicates annotated class is a Service component in the business layer.
#Controller: Annotated class indicates that it is a controller components, and mainly used at presentation layer.
You can declare a #service as #Controller.
You can NOT declare an #Controller as #Service
#Service
It is regular. You are just declaring class as a Component.
#Controller
It is a little more special than Component.
The dispatcher will search for #RequestMapping here.
So a class annotated with #Controller, will be additionally empowered with declaring URLs through which APIs are called
Controller will handle the navigation between the different views. Your mappings request mappings are handled with the help of controller.
Service interacts directly with the repository where usually the business logic is performed. You can add, delete, remove etc at the service layer
No you can't they are different. When the app was deployed your controller mappings would be borked for example.
Why do you want to anyway, a controller is not a service, and vice versa.
From Spring In Action
As you can see, this class is annotated with #Controller. On its own, #Controller doesn’t do much. Its primary purpose is to identify this class as a component for component scanning. Because HomeController is annotated with #Controller, Spring’s component scanning automatically discovers it and creates an instance of HomeController as a bean in the Spring application context.
In fact, a handful of other annotations (including #Component, #Service, and #Repository) serve a purpose similar to #Controller. You could have just as effectively annotated HomeController with any of those other annotations, and it would have still worked the same. The choice of #Controller is, however, more descriptive of this component’s role in the application.
Both are special form of #Component annotation.
Both #controller and #serviec, share same functionalities of #component annotation along with their own functionalities.
#Controller is a class-level annotation and it marks the class as web request handlers. For further explanation you can refer to this website: https://www.baeldung.com/spring-controller-vs-restcontroller
#Service is also a class-level annotation and it contains a business logic.
For further explanation you can refer to this website: https://www.baeldung.com/spring-component-repository-service

Resources