Lets say I have the following classes
#Data
#Component
public class Student {
#Autowired
private Vehicle vehicle;
}
public interface Vehicle{}
#Component
public Jeep implements Vehicle{}
#Component
public Van implements Vehicle{}
How does Spring Boot know which type of Vehicle to put in my Student object?
I know Guice has Modules which defines exactly how a certain object is built with #Provides and #Singleton coupled with #Inject in the classes that require the object.
Does Spring Boot have the same thing?
To access beans with the same type we usually use #Qualifier(“beanName”) annotation.
#Data
#Component
public class Student {
#Autowired
#Qualifier("Jeep")
private Vehicle vehicle;
}
public interface Vehicle{}
#Component
#Qualifier("Jeep")
public Jeep implements Vehicle{}
#Component
#Qualifier("Van")
public Van implements Vehicle{}
and you can annotate your default bean with #Primary so that if no qualifier is there this bean will be selected
#Data
#Component
public class Student {
#Autowired
private Vehicle vehicle;
}
public interface Vehicle{}
#Component
#Primary
public Jeep implements Vehicle{}
#Component
public Van implements Vehicle{}
Short answer: Yes
#Component
public class Student {
#Autowired
#Qualifier("jeep")
private Vehicle vehicle;
}
public interface Vehicle{}
#Component("jeep")
public Jeep implements Vehicle{}
#Component("van")
public Van implements Vehicle{}
Related
I have an interface, and there are some implementations for this. Each implementation belongs to some type.
I want that when I'm using autowired I would able to get all the implementation of the certain type. How can I do it?
public interface someInterface{}
public class impl1OfType1 implements someInterface{}
public class impl2OfType1 implements someInterface{}
public class impl1OfType2 implements someInterface{}
public class impl2OfType2 implements someInterface{}
public class someClass{
#autowired
public someClass(List<someInterface> interfaceList){}
}
I want to get only impl1OfType1 and impl2OfType1. And not all the implementation.
And at other place I want to get only impl1OfType2 and impl2OfType2.
more concrete example -
public interface EntityCreator{
createEntity();
}
#Component
public class DogCreator implements entityCreator{}
#Component
public class CatCreator implements entityCreator{}
#Component
public class CarCreator implements entityCreator{}
#Component
public class TruckCreator implements entityCreator{}
#Component
public class AnimalsFactory{
#Autowired
public AnimalsFactory(List<EntityCreator> creators){}
}
The solution would be using #Qualifier.
#Component
#Qualifier("place1")
class Impl1OfType2 implements SomeInterface {}
#Component
#Qualifier("place1")
class Impl2OfType2 implements SomeInterface {}
#Service
class SomeClass {
#Autowired
public SomeClass(#Qualifier("place1") List<SomeInterface> interfaceList) {
System.out.println(interfaceList);
}
}
I slightly changed the names to adhere to the Java convention. They are still a bit awkward and contextless.
UPDATE
You might use generics, Spring is good at dealing with them. For instance, it will inject only DogCreator and CatCreator into a List<EntityCreator<Animal>>.
interface Animal {}
interface Machine {}
interface EntityCreator<T> {}
#Component
class DogCreator implements EntityCreator<Animal> {}
#Component
class CatCreator implements EntityCreator<Animal> {}
#Component
class CarCreator implements EntityCreator<Machine> {}
#Component
class TruckCreator implements EntityCreator<Machine> {}
#Component
class AnimalsFactory {
#Autowired
public AnimalsFactory(List<EntityCreator<Animal>> creators) { }
}
UPDATE 2
You could write marker interfaces which would break down existing implementations into logical groups.
interface AnimalCreator {}
interface EntityCreator<T> {}
#Component
class DogCreator implements EntityCreator, AnimalCreator {}
#Component
class CatCreator implements EntityCreator, AnimalCreator {}
#Component
class AnimalsFactory {
#Autowired
public AnimalsFactory(List<AnimalCreator> creators) {
System.out.println(creators);
}
}
If you correct your code with above comments and I understand your problem, I assume this can be a way to solve your issue.
public interface Someinterface<T extends someType> {}
public class someType{}
public class Type1 extends someType{}
public class Type2 extends someType{}
public class TypedInterface1 implements Someinterface<Type1> {}
public class TypedInterface2 implements Someinterface<Type2> {}
public class someClass{
#Autowired
public someClass(List<TypedInterface1> interfaceList){}
}
Let me know if I answered your question.
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.
I am trying to define an architecture for my project on spring boot
What I have do is to create a generic Repository that extends from JpaRepository
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
}
After that, each EntityDao will extends from BaseRepository
#Repository
public interface AuthorityDao extends BaseRepository<Authority, Long> {
Authority findById(Long idRole);
Authority findByRoleName(String findByRoleName);
}
This is how I do it on the repository layer. At the Service Layer, I create a class named GenericService which implements IGenericService and I inject into it my BaseRepository:
#Service
public class GenericService<T, D extends Serializable> implements IGenericService<T, D> {
#Autowired
#Qualifier("UserDao")
private BaseRepository<T, D> baseRepository;
// implemented method from IGenericService
}
And each Service will extends from GenericService:
public class AuthorityService extends GenericService<Authority, Long> implements IAuthorityService {
#Autowired
GenericService<Authority, Long> genericService;
When I run the project, I get this error:
APPLICATION FAILED TO START
Description:
Field baseRepository in fr.java.service.impl.GenericService required a bean of type 'fr.config.daogeneric.BaseRepository' that could not be found.
Action:
Consider defining a bean of type 'fr.config.daogeneric.BaseRepository' in your configuration.
How can I solve this problem?
UPDATE:
#SpringBootApplication
#EntityScan("fr.java.entities")
#ComponentScan("fr.java")
#EnableJpaRepositories("fr.java")
#EnableScheduling
#EnableAsync
#PropertySource({ "classpath:mail.properties", "classpath:ldap.properties" })
#EnableCaching
#RefreshScope
public class MainApplication extends SpringBootServletInitializer {
private static final Logger log = LoggerFactory.getLogger(MainApplication.class);
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MainApplication.class);
}
public static void main(String[] args) {
log.debug("Starting {} application...", "Java-back-end-java");
SpringApplication.run(MainApplication.class, args);
}
}
You have this problem because you create GenericService as a bean and trying to inject BaseRepository but Spring can't do that because it isn't clear by which classes BaseRepository is parametrised.
From my side I can suggest you to do next: at first you GenericService shouldn't be a bean, all his children will be the beans, your should remove injecting of GenericService in your children classes, they already extends of it. Your GenericService should be abstract and it can have abstract method getRepository which will use inside GenericService, and injection of repository will be done in GenericService children classes.
So you should have something like this:
public abstract class GenericService<T, D extends Serializable> implements IGenericService<T,D> {
abstract BaseRepository<T, D> getRepository();
}
#Service
public class AuthorityService extends GenericService<Authority, Long> implements IAuthorityService {
#Autowired
BaseRepository<Authority, Long> baseRepository;
public BaseRepository<Authority, Long> getRepository() {
retrurn baseRepository;
}
}
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;
}
I have the following classes and interfaces:
public interface IPersistentObject { }
public class PersistentObject implements IPersistentObject { }
public interface IPersistentObjectDAO { }
public class PersistentDAO implements IPersistentObjectDAO { }
public interface IService1 { }
public class Service1 implements IService1{
#Autowired
private IPersistentObjectDAO persistentDAO;
}
public interface IService2 { }
public class Service2 implements IService2 {
#Autowired
private Iservice1 service1;
}
public class Bean {
private IService2 service2 = JSFUtil.resolveBean("service2");
}
<bean name="service1" class="Service1"/>
<bean name="service2" class="Service2"/>
My question is: How should i modelling these associations?
If it can help I'm using JSF, Spring and Hibernate
If you use interface, it means what your model should be
JSF bean/ inject - interface->implemented class(DAO)->DB entity
So your JSF beans should find and inject Spring interfaces.
Spring service can be separated jar, which you can inject to JSF front end .
in jsf
#ManagedProperty("#{handlerService}")
private HandlerService handlerService = null;
Spring
#Service("handlerService")
#Component
public class HandlerService {
#Autowired
private DomainService domainService;
If your problem is just modeling, just look here: http://www.uml-diagrams.org/generalization.html You will have to point FROM the class that implement TO the interface. Like: "Service2" ---l> "IService2"
If it's something else, please clarify your answer.
For Interfaces, the relation to its implementors is called "realization" not "generalization".
And it goes from the Interface to the Class that realize it, see below.
Class ----> Interface