I'm in the process of migrating to Spring Boot 3. In Spring Boot 2 Resilience4J Retry was auto-configured and worked out of the box using the following setup:
application.yaml:
resilience4j.retry:
instances:
some-instance
# retry config here
Test class:
#SpringBootTest
public class TestClass {
#Autowired
private RetryRegistry retryRegistry;
#Test
void someTest() {
// perform test and evaluate retries using retryRegistry
}
}
However while updating to Spring Boot 3 using the following versions:
org.springframework.boot:spring-boot-starter:jar:3.0.0:compile
io.github.resilience4j:resilience4j-spring-boot2:jar:1.7.0:compile (derived from a Spring BoM)
The test in which the RetryRegistry was autowired failed with the following message:
Unsatisfied dependency expressed through field 'retryRegistry':
No qualifying bean of type 'io.github.resilience4j.retry.RetryRegistry' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I managed to fix the test by explicitly importing the Resilience4j Retry configuration in the test using:
#Import(io.github.resilience4j.retry.autoconfigure.RetryAutoConfiguration.class)
However, I'm wondering why the component scanning mechanism in Spring Boot 3 did not pick up the retry config in the first place. Would anyone know why Spring Boot 3 did not pick up the class during component scanning?
In the resilience4j project they changed the dependency for spring boot 3.
So you should go for io.github.resilience4j:resilience4j-spring-boot3:${resilience4jVersion}
like
org.springframework.boot:spring-boot-starter:jar:3.0.0:compile
io.github.resilience4j:resilience4j-spring-boot3:jar:2.0.0:compile
from the documentation
It seems that it is related to a new META-INF file being used instead of the old spring.factories file. From the documentation :
Spring Boot 2.7 introduced a new META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports file for registering auto-configurations, while maintaining backwards compatibility with registration in spring.factories. With this release, support for registering auto-configurations in spring.factories has been removed in favor of the imports file.
The Resilience4J dependency used in the spring-cloud-dependencies-parent BoM still uses a spring.factories file instead of the new file named org.springframework.boot.autoconfigure.AutoConfiguration.imports. The new file has recently been introduced in Resilience4J (source).
Overriding the version from the Spring BoM with version 2.0.2 for all the resilience dependencies fixed it for me. I will check in a few days whether the new Resilience4J version has been updated in the Spring BoM (or resilience4j-spring-boot3 has been introduced).
[edit]
As others have noticed,resilience4j-spring-boot3 is already available. I'll start using it.
Related
So I have I built a custom Springboot starter and autoconfiguration and everything builds fine, the code is all their in the local maven repo.
I even checked the generated jars and everything looksgood.
Can't load the generated files into the project but when I look at the generated beens, there is no sign of beans created by autoconfiguration (or the autoconfiguration itself) : https://github.com/orubel/spring-boot-starter-beapi/issues/37
Project code can be sen here: https://github.com/orubel/spring-boot-starter-beapi/blob/main/beapi-lib/build.gradle
what am I doing wrong that implementations can';t see the beans?
I have tried bringing in the dependencies from mavenLocal() with:
implementation "io.beapi:beapi-lib:0.4"
implementation "io.beapi:beapi-spring-boot-starter:0.4"
and with:
implementation "io.beapi:beapi-lib:0.4"
implementation "io.beapi:beapi-spring-boot-autoconfigure:0.4"
Both have the same error of stating that an AUTOWIRED bean (from the autoconfiguration) cannot be found:
Consider defining a bean of type 'io.beapi.lib.service.PrincipleService' in your configuration.
If I comment out the autowired bean, it just throws error that bean is null.
Ok solved my issue.
As I am instantiating the beans from a library I am creating through the starter, I have to do a '#ComponentScan' on those classes.
So just adding:
#ComponentScan(["io.beapi.lib.service"])
To the application main class was enough to resolve this :)
In my Vaadin and Spring Boot application, I have updated from jOOQ 3.14.12 to 3.15.0. After this update my application is not starting up again. This is the error I get:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in org.komunumo.data.service.MemberService required a bean of type 'org.jooq.DSLContext' that could not be found.
Action:
Consider defining a bean of type 'org.jooq.DSLContext' in your configuration.
I don't understand why I have to define this bean, because with jOOQ 3.14.12 I did not have to. As far as I know, this is done by JooqAutoConfiguration automatically.
Spring Boot 2.6 answer
With Spring Boot 2.6, this issue no longer reproduces, see https://github.com/spring-projects/spring-boot/issues/26439
Spring Boot 2.5 answer
Starting from jOOQ 3.15.0, jOOQ ships with a built-in R2DBC dependency. Spring Boot 2.5 is not yet aware of this, and as such, you'll have to explicitly exclude R2dbcAutoConfiguration (not R2dbcDataAutoConfiguration!) from your spring boot application (unless you're using R2DBC with jOOQ, of course):
#SpringBootApplication(exclude = { R2dbcAutoConfiguration.class })
Note, you may see the following error message:
No qualifying bean of type 'org.jooq.DSLContext' available: expected at least 1 bean which qualifies as autowire candidate.
Which I'm adding here, because otherwise, people might not find this answer from Google.
I am building a jar dependency that will create a bean of a type that is likely to exist already in the apps that will use that dependency.
I want to create a configuration spring class in the dependency to mark that bean as "secondary".
How can we set explicitly a bean as secondary (or #Primary(value=false) ) in spring with annotations or with java config?
There is also the autoWireCandidate on the #Bean annotation. But that is available only from the very young spring versions.
I have created a Spring Boot application managed by Maven.
I'm retrieving an company's library from our Maven repository.
In this library, we have a service interface, not being annotated with '#Service':
public interface MyService {
//...
}
This service has only one implementation :
public class DefaultMyService implements MyService {
//...
}
This library context is managed the old Spring way (in applicationContext.xml file).
I read that normally, Spring Boot is able to find the implementation if there's only one in the scope.
When I try to run "spring-boot:run" on my project, it will fail with the following error :
No qualifying bean of type 'com.pharmagest.saml.SAMLService'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
I tried:
To add a #ComponentScan on the configuration class, including packages in error : #ComponentScan(basePackages={"com.mycompany.web", "com.mycompany.thelibrary.client.*", "com.mycompany.thelibrary.services.*"})
To add the bean definition in applicationContext.xml (if I add the interface it tells me it can define it, thus I heard that Spring can find the default implementation if there is only one ?)
To add library at "runtime" in projects options
To add the library as external resource not via maven
In all cases I just can maven build but can't run the project.
Do you have any advice to help me ? thanks!
Won't work as the DefaultMyService has no #Component (or #Service) annotation will not be detected.
Bean definition has to be a concrete instance so use DefaultMyService instead of the interface. Spring will not detect anything for you your understanding is wrong
and 4. Will not change anything only adding dependencies without proper 1. or 2. will do nothing.
Just add a #Bean to your configuration
#Bean
public DefaultMyService myService() {
return new DefaultMyService();
}
Or import the other libraries applicatiponContext.xml which is what you probably should do.
#ImportResource("classpath:/applicationContext.xml")
Add this next to the #SpringBootApplication.
In my sample spring boot application, i have added a dependency of a custom jar. My sample application has a support for web and jpa.
The jar which i've created contains a Spring MVC controller. Below is the sample code
#Controller
public class StartStopDefaultMessageListenerContainerController {
#Autowired(required=false)
private Map<String, DefaultMessageListenerContainer> messageListeners;
I haven't manually created a bean instance of this controller anywhere in my code.
Problem - When i start my spring boot application by running the main class, i get an error in console that prob while autowiring DefaultMessageListenerContainer.
My question here is, even though this class StartStopDefaultMessageListenerContainerController is just present in the classpath, it's bean shouldn't be created and autowiring should not happen. But spring boot is scanning the class automatically and then it tries to autowire the fields.
Is this the normal behavior of spring and is there anyway i can avoid this?
If the StartStopDefaultMessageListenerContainerController class is part of component scanning by spring container, Yes spring tries to instantiate and resolve all dependencies.
Here your problem is #Autowired on collection. Spring docs says,
Beans that are themselves defined as a collection or map type cannot be injected through #Autowired, because type matching is not properly applicable to them. Use #Resource for such beans, referring to the specific collection or map bean by unique name.
And also Refer inject-empty-map-via-spring