Issue
How exactly does the @ConditionalOnClass
annotation work?
My goal is to load a specific bean only if the jar
providing this class is included in the classpath.
I thought the I could annotate a @Bean
with @ConditionalOnClass(MyService.class)
and declaring the dependency in maven as optional:
<dependency>
<groupId>de.my</groupId>
<artifactId>my-framework<artifactId>
<optional>true</optional>
</dependency>
@Bean
@ConditionalOnClass(MyService.class)
public MyConditionalBean statistics() {
return new MyConditionalBean();
}
Now, anyone having my-framework
as dependency should get that bean automatically wired. But anyone not having the dependency should skip it.
But when I start the app, I get the following error:
Caused by: java.lang.ClassNotFoundException: de.MyService.class
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1702) ~[catalina.jar:7.0.50]
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547) ~[catalina.jar:7.0.50]
So I'm probably doing something wrong. How can I then create the bean conditional on the dependency jars and the classes contained in the classpath?
From the spring docs:
The classes that must be present. Since this annotation parsed by loading class bytecode it is safe to specify classes here that may ultimately not be on the classpath.
But the error states different...
Solution
Good catch!
You can use on @Bean
method level, but in that case you have to specify your class as a String literal:
@Bean
@ConditionalOnClass(name ="de.MyService")
public MyConditionalBean statistics() {
return new MyConditionalBean();
}
I don't remeber already "why", but it is from an existing code of Spring Boot sources.
Answered By - Artem Bilan
Answer Checked By - David Goodson (JavaFixing Volunteer)