Spring #Bean annotation differences (context vs config packages)? - spring

What is the difference between these classes and when should I use each in conjunction with #Configure?
org.springframework.context.annotation.Bean
org.springframework.config.java.annotation.Bean;

It looks like you have an obsolete jar file in your classpath - org.springframework.config.java.annotation.Bean is no longer with the latest Spring 3.1.2 jars, it is the org.springframework.context.annotation.Bean annotation that should be used with the #Configuration classes

The JavaConfig dependency is part of the spring-context as of Spring 3.0. Therefore if you are building your app using Spring > 3.0 use the org.springframework.context.annotation.Bean

Related

How do I use the OpenTelemetry component in Apache Camel?

Using the Spring Boot example from Camel, I'm trying to set up OpenTelemetry to instrument Camel.
Based on the docs, I chose the Spring Boot Auto-configuration option and added the dependency to my pom.xml.
I've also annotated the main class with #CamelOpenTelemetry:
package sample.camel;
import org.apache.camel.opentelemetry.starter.CamelOpenTelemetry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//CHECKSTYLE:OFF
/**
* A sample Spring Boot application that starts the Camel routes.
*/
#CamelOpenTelemetry
#SpringBootApplication
public class MyCamelApplication {
...
I started the application with OTEL_TRACES_EXPORTER=logging mvn spring-boot:run.
Is this correct? I'm not seeing any console output unlike this simple OpenTelemetry example.
I'm not sure if Camel 3.x is supported because this page says only 2.20+ is supported but Camel's docs says Since Camel 3.5 at the top.

ComponentScan does not find own custom annotations after update from Spring Boot 2.0.3 to 2.2.4

Prior to the update from Spring Boot 2.0.3 to 2.2.4 we had some annotations like the following example:
import org.springframework.stereotype.Component;
#Component
public #interface Adapter {
}
During ComponentScan classes annotated with this Adapter annotation got picked up and added to the Spring context. After the update there are now org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'XY' available.
According to a passage in the Terminology of the Spring Annotation Programming Model regarding Stereotype Annotations our approach should work:
Any component annotated with #Component is a candidate for component scanning. Similarly, any component annotated with an annotation that is itself meta-annotated with #Component is also a candidate for component scanning.
I read through the release notes of Spring Boot 2.1 and 2.2 and the release notes of the Spring Framework 5.1 and 5.2, but found nothing that the behaviour of stereotype annotations changed in this point.
When I annotate the classes with a Spring provided stereotype annotation (in addition to our own annotation) they get picked up by the ComponentScan.
I also tried to set a custom filter in a #ComponentScan like this
#ComponentScan(includeFilters = #ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = Adapter.class))
but still got the NoSuchBeanDefinitionException
At last I stumbled upon this "Enhancement" in the Spring Framework and wonder if this could be the root of my problem.
So nothing worked so far and I would be glad if someone could point me in a direction that restores the original behaviour that our own stereotype annotations are working again. Thanks in advance.
After taking a closer look at the Spring Stereotype annotations adding #Retention(RetentionPolicy.RUNTIME) to our annotations solved the issue. The classes with our own annotations get picked up by ComponentScan again.
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.springframework.stereotype.Component;
#Retention(RetentionPolicy.RUNTIME)
#Component
public #interface Adapter {
}

Spring boot auto configuration with dependency and without #ComponentScan

Spring boot provides #ComponentScan to find packages to be scanned.
I am building a library which has #RestControllers inside with package com.mylib.controller. There are other classes as well with stereotype annotations in different packages.
So, if some one is developing SpringBoot Application with com.myapp base package.
He uses my library in his application. He need to mention #ComponentScan("com.mylib") to discover stereotype components of library.
Is there any way to scan components without including library package in #ComponentScan?
As spring-boot-starter-actuator expose its endpoints just with dependency, without defining #ComponentScan. OR any default package which is scanned regardless of application base package.
You could create a Spring Boot Starter in the same style as the Spring Provided Starters. They are essentially a jar'd library with a a spring.factories file pointing to the #Configuration class to load with some other annotations on there to provide overriding/bean back off (#ConditionalOnMissingBean) and generally provide their own #ConfigurationProperties.
Stéphane Nicoll provided an excellent demo of how to build one.
https://github.com/snicoll-demos/hello-service-auto-configuration
It is also documented in the Spring Boot documentation. https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
The library approach would also work but I see no benefit in not making it a starter. Additionally for any library/starter I'd recommend dropping the #ComponentScan and just defining the beans in a #Configuration. This will work for sterotypes like #RestController etc. will function as normal if you create an #Bean out of it in a configuration.
Spring boot starter are special artifacts designed by Spring and used by Spring.
You can check that in the source code that contains mainly a
spring.provides file :
provides: spring-boot-actuator,micrometer-core
I don't know the exact way to process in the same way as Spring Boot Starter but as probably acceptable workaround, you could define in your jar a #Configuration class that specifies #ComponentScan("com.mylib").
#Configuration
#ComponentScan("com.mylib")
public class MyLibConfig {
//...
}
In this way, clients of the jar need "only" to import the #Configuration class :
#Import(MyLibConfig.class)
#Configuration
public class ClientConfig{
//...
}

Why AutoConfigurationPackages not consider #ComponentScan?

Spring Boot's support for Spring data configuration is generally by org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport, and this class use the follow code to determine what packages to scan for repositories:
AutoConfigurationPackages.get(this.beanFactory)
So, basically Spring Data with Spring Boot only scan the package which contains the #EnableAutoConfiguration or #ImportAutoConfiguration, but not consider the #ComponentScan, Is this correct ?
The #ComponentScan annotation is a core Spring Framework feature to search for classes annotated with #Component. Since Spring Data repositories are interfaces (and not annotated), the #ComponentScan annotation won't pick them up.
If you are using Spring Data outside of Spring Boot, you can scan for Spring Data repositories using #EnableJpaRepositories with the basePackages attribute set.
When it comes to Spring Boot, there's usually no need to use either #ComponentScan or #EnableJpaRepositories. If you structure your code as suggested, both components and repositories will be picked up.
To get back to your original question about AbstractRepositoryConfigurationSourceSupport. If you look at the source of #SpringBootApplication you'll see it's annotated with #ComponentScan (to find #Components) and #AutoConfigurationPackage (via #EnableAutoConfiguration). The #AutoConfigurationPackage sets up AutoConfigurationPackages with the value that's later retrieved.
If you want to override the packages the Spring Data searches for repositories (for example in tests) you'll need to use #EnableJpaRepositories to completely override auto-configuration. I usually don't do this, but instead use #DataJpaTest and pick up my main configuration.

Spring #ComponentScan annotation

Why do we use #ComponentScan annotation in spring ? I am not being able to figure out the exact difference between context:componentscan in xml file and #ComponentScan annotations in java and how to use them in case of classes which have been annotated with #Configuration
In short, there is no difference.
#ComponentScan - Used with #Configuration classes, for example, when you have java-based configurations for Spring.
It provides support parallel with Spring XML's <context:component-scan> element. The purpose of those two are exactly the same - to scan spring components.
But there is one advantage of xml based configuration - you don't need to compile your java code. When you added some package under <context:component-scan> then you don't need to compile java source code. Place the xml configuration file in your server and restart it.

Resources