• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Bear Bibeault
  • Jeanne Boyarsky
  • Tim Cooke
Sheriffs:
  • Knute Snortum
  • Junilu Lacar
  • Devaka Cooray
Saloon Keepers:
  • Ganesh Patekar
  • Tim Moores
  • Carey Brown
  • Stephan van Hulst
  • salvin francis
Bartenders:
  • Ron McLeod
  • Frits Walraven
  • Pete Letkeman

Spring: how to deal with multiple implementations of a given service interfaces ?  RSS feed

 
Ranch Hand
Posts: 996
9
IBM DB2 Java Netbeans IDE Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Howdy there, I've a couple of questions for Spring experts here.
Let's say I have a service interface, for example a very simple one like this:



and different implementations I want Spring to treat as @Services:



I want to know how I could select, at runtime, which concrete implementation to use. In another @Service or @Component annoted class I could autowire directly an instance of ISmartService this way, provided that there's no ambiguity on which concrete class to inject:



First of all, I wonder if autowiring interfaces is a good practice or not in Spring: generally speaking, working with interfaces and avoid coupling with concrete classes is a good design practice (when it's possibile, of course), but I've read somewhere that in Spring using interfaces instead of concrete beans isn't a good habit.
Honestly, I don't understand why.

Second: to avoid ambogous bean referencing, I need to specify which is the default implementation of ISmartService  I want to use. To achieve this,  I thought to use a @Configuration class defined this way:



If I had not a @Primary factory defined, Spring fx would complain because it would not be able to choose which implementation to inject. I choose to use a @Configuration class, but I don't know if it's a good practice or not to mark as @Primary a bean producer method.

Third - and last question at the moment :-) - : what's the best or more largely used strategy to select which implementation to use ?
Two options came to my mind: the first option is to use profiles. I could run separated instances of my program and select concrete implementations on an active profile basis.
The second option is to implement an SPI based solution: i could annotate each service with a custom annotation, for example @Standard and @Custom, and let my program act this way: if an implementation marked as @Custom is present in the classpath, then inject it; otherwise, inject the standard implementation.

What are you suggestions, guys ?
Thanks for your help in advance.



 
Sheriff
Posts: 21503
96
Chrome Eclipse IDE Java Spring Ubuntu VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can put @Primary on a class as well, no need to use an @Configuration class for that.

There are two ways I can think of to get non-primary bean instances:
1) Inject a List<ISmartService>. Spring will find all implementations. You can then select anything you want from this list.
2) Use qualifiers. Both the provider (the class or @Bean method) and the lookup (the autowired field / constructor argument / ...) must use the same qualifier. I'm not sure if this has the power of CDI's Instance's select method, where you can do a lookup directly on an injected Instance.

See https://www.baeldung.com/spring-autowire for a bit more information.
 
Claude Moore
Ranch Hand
Posts: 996
9
IBM DB2 Java Netbeans IDE Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Rob Spoor wrote:You can put @Primary on a class as well, no need to use an @Configuration class for that.



That's true, but I feel that using a @Configuration class allows more flexibility.

Rob Spoor wrote:
1) Inject a List<ISmartService>. Spring will find all implementations. You can then select anything you want from this list.



Great advice, thanks. I tried it and worked beautifully.
Since I want to build an extensible application, I though to adopt SPI. What do you think about it ? Is it an obsolete technology ?
 
Claude Moore
Ranch Hand
Posts: 996
9
IBM DB2 Java Netbeans IDE Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've tried with further tests. Looks like that using SPI is necessary, at least if you want to instantiate beans definited in "pluggable" jars. Anyway I think that Rob's suggestion, i.e inject a list of all available service of a given type, it's the most straightforward approach when all bean are co-located in the same spring project.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!