Same interface from multiple type - java

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.

Related

How to inject this or that implementation depending on configuration a parameter with Spring

I am using the Spring/Springboot framework and would like to know if there is a possibility to "choose" or "select" the implementation class to instanciate depending on a configuration parameter
Let's say I have an interface IMyInterface and two possible implementations IImplentation1 and IImplementation2
I also have a class FooBar whose constructor receives a configuration class MyConf and an instance of IMyInterface
#Component
interface IMyInterface {
}
class IImplentation1 implements IMyInterface {
}
#Component
class IImplentation2 implements IMyInterface {
}
#Component
#ConfigurationProperties("my.application")
#Validated
class MyConf {
String kind; /// could be an enum
}
class IImplentation2 implements IMyInterface {
}
#Component
class FooBar {
#Autowired
public FooBar(MyConf myConf,
IMyInterface myInterface) { /// IImplentation1 or IImplentation2
... /// depending on MyConf.kind
}
}
Thanks for help
Regards
Philippe

How does Spring Boot know which object to inject?

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{}

More than one ejb found with interface of type for binding

I have an interface like this:
#Local
public interface MyInterface {
}
And two classes that implements this interface:
#Singleton
public class FirstBean implements MyInterface {
}
#Singleton
public class SecondBean implements MyInterface {
}
And another class like below:
#Singleton
public class ThirdBean {
#EJB
private MyInterface xpto;
}
And i am receiving the following error on deploy:
More than one ejb found with interface of type for binding
How to solve it?
Try to use qalifier
#java.lang.annotation.Documented
#java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE,ElementType.FIELD})
#javax.inject.Qualifier
public #interface First {
}
Mark bean using this qualifier
#Singleton
#First
public class FirstBean implements MyInterface {
}
Then inject it
#Singleton
public class ThirdBean {
#Inject
#First
private MyInterface xpto;
}

Field required a bean of type that could not be found on Generic JPA DAO architecture

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;
}
}

Roboguice - Two implementations for one interface

My code is like this:
interface MyIntreface{
...
}
class A implements MyInterface{}
class B implements MyInterface{}
class BaseClass{
#Inject
MyInterface instance;
}
class MyFirstClass extends BaseClass{
....
}
class MySecondClass extends BaseClass{
....
}
Now I want to MyFirstClass have implementation A and MySecondClass implementation B. #Named annotations seems not to work in this case. Is there any other robo-solution ?
This use case is impossible to implements using Roboguice. But there are two ways to resolve your problem.
Implement provider that injects MyFirstClass and MySecondClass and then inject to provider A or B and use setter to set it in created instance
class Baclass BaseClass{
protected abstract MyInterface extractMyInterface();
}
class MyFirstClass extends BaseClass{
#Inject
B instance;
protected MyInterface extractMyInterface() {
return instance;
}
}
class MySecondClass extends BaseClass{
#Inject
A instance;
protected MyInterface extractMyInterface() {
return instance;
}
}
In my opinion the first one (with Provider) is much more cleaner.

Categories

Resources