How to #Autowired a concrete implementation of a service? - java

I have the following situation:
public interface ServiceAura extends Serializable { }
#Service
public class ServiceA implements ServiceAura {
....
}
#Service
public class ServiceB implements ServiceAura {
....
}
Now from the controller I need to call both of them by separate:
#Path("")
#Controller
public class ServiciosAuraPortalRESTfulService {
#Autowired
private ServiceAura srvA;
#Autowired
private ServiceAura srvB;
}
I have read about #Qualified, is this the only way? How can I archive this?

You're right. You can use #Qualifier("ServiceA") to specify which implementation you want to autowire.
#Path("")
#Controller
public class ServiciosAuraPortalRESTfulService {
#Autowired
#Qualifier("ServiceA")
private ServiceAura srvA;
#Autowired
#Qualifier("ServiceB")
private ServiceAura srvB;
}
On the service itself, you can use the annotation #Primary to specify which one is the default implementation that you want.
Alternatively, you can use the application context to retrieve a specific bean. You'll need to autowire the ApplicationContext class and then retrieve it with ServiceAura srvA = context.getBean(ServiceA.class);

There are two ways to do this.
The first way is using #Qualifier annotation as you've stated.
#Path("")
#Controller
public class ServiciosAuraPortalRESTfulService {
#Autowired
#Qualifier("serviceA")
private ServiceAura srvA;
#Autowired
#Qualifier("serviceB")
private ServiceAura srvB;
}
Your services should be defined like this:
#Service
#Qualifier("serviceA")
public class ServiceA implements ServiceAura {
....
}
#Service
#Qualifier("serviceB")
public class ServiceB implements ServiceAura {
....
}
Another way is to create interfaces that extend interface ServiceAura
interface ServiceAInterface extends ServiceAura {
}
class ServiceA implements ServiceAInterface {}
.... // the same for service B
And then in code:
public class ServiciosAuraPortalRESTfulService {
#Autowired
ServiceAInterface serviceA;
}

Related

What is the difference between using #Qualifier annotation and directly injecting bean in spring?

Suppose I have a program
#Component
public interface Coach{
public String giveCoaching();
}
#Component
public TennisCoach implements Coach{
#Override
public String giveCoaching(){
return "Teaching forhand";
}
}
I have two Demo classes in which I have injected the bean in different ways. what is the difference in both the injections
public class AppDemo{
#AutoWired
#Qualifier("tennisCoach")
private Coach theCoach;
}
public class AppDemo{
#AutoWired
private TennisCoach tennisCoach;
}
}
When you have more than 1 implementation for you interface, you will get an exception when Autowiring the bean. At that time #Qualifier will be used to choose the required implementation
#Component
public interface Coach{
public String giveCoaching();
}
#Component
public TennisCoach implements Coach{
#Override
public String giveCoaching(){
return "Teaching forhand";
}
}
#Component
public CricketCoach implements Coach{
#Override
public String giveCoaching(){
return "Teaching forbat";
}
}
Now the ambiguity will occur when you autowire the Coach Interface like below
public class AppDemo{
#AutoWired
private Coach theCoach;
}
So you have to qualify the right bean for the CoachInterface like below.
public class AppDemo{
#AutoWired
#Qualifier("tennisCoach")
private Coach theCoach;
}
Alternatively you can use #Primary annotation on top of any one of the implementation so that the Spring Container will by default choose the bean in case of more than 1 implementation for an interface.
But in the code below, you are directly creating the object for the implementation rather than interface.
public class AppDemo{
#AutoWired
private TennisCoach tennisCoach;
}
}
#Qualifier annotation is used when your interface has more than one implementing class, You should opt for the one you want inject as a bean in spring context.

Field ClientService required a bean that could not be found in Spring

This is my ClientService class :
public interface ClientService{
public void saveClient(Client client);
}
This is the implementation :
#Service("clientService")
public class ClientServiceImpl{
#Autowired
private ClientRepository clientRepository;
public void saveClient(Client client) {
clientRepository.save(survey);
}}
This is my repository:
#Repository("clientRepository")
public interface ClientRepository extends JpaRepository<Client, Long> { }
And in my controller I have :
#Controller
public class LoginController {
#Autowired
private ClientService clientService;
which I then try to access
clientService.save in the function.
What annotation could I possibly be missing or what am I doing wrong ?
Cuz I've done this the same way before and it has worked for other services.
Thank you
Fixed it!
I had forgotten implements ClientService in the ClientServiceImplementation class!

How to autowire Spring service with Class name?

I have multiple services and I want to autowire this services dynamically with using their class names. I have a method named "runCustomService" and this methods takes service's class names as input parameter (like "Service1" or "Service2"). I want to autowire these services and call its run method. Is there any way to do this?
#Service
public class Service1 extends BaseService{
#Autowired
private AnotherService anotherService;
public void run(){ .... }
}
#Service
public class Service2 extends BaseService{
#Autowired
private AnotherService anotherService;
public void run(){ .... }
}
public void runCustomService(String serviceClassName){
BaseService baseService = //Create baseService object from serviceClassName
baseService.run();
}
You could use qualifiers on your two services and get the correct bean based on the qualifier name from the ApplicationContext.
#Service
#Qualifier("Service1")
public class Service1 extends BaseService{
#Service
#Qualifier("Service2")
public class Service2 extends BaseService{
#Autowired
ApplicationContext applicationContext;
public void runCustomService(String serviceClassName){
BaseService baseService = applicationContext.getBean(serviceClassName);
baseService.run();
}
Get an instance of ApplicationContext and get bean by a class name:
#Autowired
ApplicationContext ctx;
Use the method getBean(...):
BaseService baseService = ctx.getBean(Service1.class.getName());
However, as the other answer says, I recommend you to use #Qualifier(...) to inject a certain named conditionally.

Autowiring of generic types doesn't work [Spring 4+]

I'm working on one project with Spring 4.2.4.RELEASE.
I've heard about new features Spring 4 (especially about autowiring of generic types), and I was confused when the following code hadn't been compiled:
#Service
public interface AuthenticationService<T> { ... }
public class VKAuthenticationService implements AuthenticationService<VKToken> { ... }
#RestController
public class VKAuthenticationController {
#Autowired
private AuthenticationService<VKToken> service;
}
Thank you in advance for any assistance.
How about also declare #Service on your VKAuthenticationService
#Service(name="myService")
public class VKAuthenticationService implements AuthenticationService<VKToken> { ... }
and use #Autowired and #Qualifier to inject it
#RestController
public class VKAuthenticationController {
#Autowired
#Qualifier("myService")
private AuthenticationService<VKToken> service;
}

Does autowiring work for classes instantiated from PerConnectionWebSocketHandler?

I can successfully read an autowired instance of HandlerSettings in the main class, so I know I have the application.properties entries correct.
#Component
#ConfigurationProperties(prefix="handler")
public class HandlerSettings {
private int timeout;
public int getTimeout(){
return timeout;
}
public void setTimeout(int timeout){
this.timeout = timeout;
}
}
I am having difficulties trying to autowire fields in the MyHandler class, which is instantiated within a PerConnectionWebSocketHandler.
#SpringBootApplication
#RestController
#EnableWebSocket
#EnableConfigurationProperties(HandlerSettings.class)
public class MyController implements WebSocketConfigurer{
#Bean
public WebSocketHandler myHandler() {
return new PerConnectionWebSocketHandler(MyHandler.class));
}
I want to autowire fields in an abstract base class of MyHandler.
#Component
public abstract class Handler implements WebSocketHandler {
#Autowired
private HandlerSettings handlerSettings;
...
}
MyHandler inherits from Handler:
public class MyHandler extends Handler
The example in the Spring documentation does not address what to do in either the case of inheritance, or the way classes are instantiated with the PerConnectionWebSocketHandler.
I have tried unsuccessfully to autowire fields in Handler. It is possible to autowire if the class is instantiated by PerConnectionWebSocketHandler? If so, is there something special I have to do to autowire the base class, but not the classes that extend it?
As per the Source Codes unless you set the PerConnectionWebSocketHandler.setBeanFactory in will instantiate a Handler without the Injected Beans.
#SpringBootApplication
#RestController
#EnableWebSocket
#EnableConfigurationProperties(HandlerSettings.class)
public class MyController implements WebSocketConfigurer {
#Autowired
private BeanFactory beanFactory;
#Bean
public WebSocketHandler myHandler() {
PerConnectionWebSocketHandler perConnectionWebSocketHandler = new PerConnectionWebSocketHandler(MyHandler.class);
perConnectionWebSocketHandler.setBeanFactory(beanFactory);
return perConnectionWebSocketHandler;
}
}

Categories

Resources