I am coding both a library and service consuming this library. I want to have a UsernameProvider
service, which takes care of extracting the username of the logged in user. I consume the service in the library itself:
class AuditService {
@Autowired
UsernameProvider usernameProvider;
void logChange() {
String username = usernameProvider.getUsername();
...
}
}
I want to have a default implementation of the UsernameProvider
interface that extracts the username from the subject claim of a JWT. However, in the service that depends on the library I want to use Basic authentication, therefore I'd create a BasicAuthUsernameProvider
that overrides getUsername()
.
I naturally get an error when there are multiple autowire candidates of the same type (DefaultUsernameProvider
in the library, and BasicAuthUsernameProvider
in the service), so I'd have to mark the bean in the service as @Primary
. But I don't want to have the library clients specify a primary bean, but instead mark a default.
Adding @Order(value = Ordered.LOWEST_PRECEDENCE)
on the DefaultUsernameProvider
didn't work.
Adding @ConditionalOnMissingBean
in a Configuration class in the library didn't work either.
EDIT: Turns out, adding @Component
on the UsernameProvider
implementation classes renders @ConditionalOnMissingBean
useless, as Spring Boot tries to autowire every class annotated as a Component, therefore throwing the "Multiple beans of type found" exception.
You can annotate the method that instantiates your bean with @ConditionalOnMissingBean
. This would mean that the method will be used to instantiate your bean only if no other UserProvider
is declared as a bean.
In the example below you must not annotate the class DefaultUserProvider
as Component
, Service
or any other bean annotation.
@Configuration
public class UserConfiguration {
@Bean
@ConditionalOnMissingBean
public UserProvider provideUser() {
return new DefaultUserProvider();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With