I have two spring bean classes which are implemeting the same interface.
public interface Abc()
{
String getNumber();
}
The two classes are
#Service
public class SomeClass implements abc
{
#Override
public class getNumber()
{
}
}
#Service
public class SomeClass1 implements abc
{
#Override
public class getNumber()
{
}
}
In my Service class.
#Service
public class Demo
{
#Autowired
private Abc abc;
}
}
I got an error "required a single bean, but 2 were found"
For that error i can have the chance to put #Primary in the top of one of the bean.
But i have only way to say "one bean configuration" based on the value which i will get in runtime(From the database).
Can you please suggest me a way.
You can autowire a list of interfaces and then choose the right one. You can write:
#Autowired
List<Abc> abcs;
this will result in a list of implementations of the interface. In your method body you can then choose the right one.
Couple of ways you can autowire the correct implementation.
Change your autowired field name to the same name of the implementation class (in camelcase)
#Autowired
private Abc someClass;
This will attempt to find an implementation of interface 'Abc' with the classname 'SomeClass'.
Another way is to add a bean name to your service annotation
#Service("someClass")
public class SomeClass implements abc
This can then be autowired like the following
#Autowired
#Qualifier("someClass")
private Abc SomeClass;
I think the problem he is asking about how to configure two implentation and also using the right bean dynamically(based on data in DB) . It seems this is the an example for factory pattern
Psuedo Code
Class SomeFactory{
#Autowired
private Abc someClass;
#Autowired
private Abc someClass1;// keeping bean Name same as class name would solve bean finding issue
public Abc getBeanFor(String type) {
if("someClass".equals(type)
return someClass;
return someClass1;
}
}
Class TestClass{
#Autowired
private SomeFactory factory ;
private void someProcess() {
// Read type from DB for data
factory.getBeanFor(typeReadFromData)
.process();
}
}
Can I make a generic class that requires the type of its generic parameter Class<T> as constructor argument available as #Bean in Spring?
Generic class:
public class Repository<T> {
public Repository(Class<T> type) {
//...
}
}
My current #Bean definitions:
#Bean
public Repository<Car> carRepository() { return new Repository<>(Car.class) }
#Bean
public Repository<Garage> carRepository() { return new Repository<>(Garage.class) }
//... one for each type I require
What I would like:
#Bean
public <T> Repository<T> genericRepository() { return new Repository<>(T.class) }
I've already looked into Spring's ResolvableType, but it doesn't seem like that's what I'm looking for. Is there a way to get a hold of T's class without requiring a constructor argument? Does spring offer a mechanism for it?
Typing to inject a typed component of a generic interface in to a generic class fails if there are 2 instances differing on type information.
#Autowired
BetterObjectPrinter<Integer> integerBetterObjectPrinter;
#Autowired
BetterObjectPrinter<String> stringBetterObjectPrinter;
public interface ObjectPrinter<T> {
public String print(T obj);
}
#Component
public class IntegerPrinter implements ObjectPrinter<Integer> {
public String print(Integer obj) {
return obj.toString();
}
}
#Component
public class StringPrinter implements ObjectPrinter<String> {
public String print(String obj) {
return obj.toString();
}
}
#Component
public class BetterObjectPrinter<T> {
#Autowired
ObjectPrinter<T> objectPrinter;
public String print(T obj) {
return objectPrinter.print(obj);
}
}
I'm wondering if this is the expected result, is there enough type information available?
The result I get is
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'hello.ObjectPrinter<?>' available: expected single matching bean but found 2: integerPrinter,stringPrinter
However it does work if ObjectPrinter is a generic class so the type information must still be available
#Component
public class ObjectPrinter<T> {
public String print(T obj) {
return obj.toString();
}
}
All works well if I create the 2 beans using #Configuration and #Bean annotations to create the 2 instances of BetterObjectPrinter
The above was tested using Spring 4.3.13.
Yes, it expected, spring does not know which one of two to auto wire to objectPrinter field. You can use #Qualifier annotation to resolve the conflict.
I have a factory class and I wonder if it is possible to inject the AnimalMapper factory class into other beans that needs it?
AnimalMapper factory class
public static Mapper create(final String type) {
if (type.equalsIgnoreCase("dog")) {
return new DogMapper();
} else if (type.equalsIgnoreCase("cat")) {
return new CatMapper();
} ...
}
Currently I am using AnimalMapper.create(...)
Here is sample code
public class TestClass{
//member variable defination.
#Inject
AnimalMapper animalMapper; //defining mapper instance
}
I am not sure if you are looking for this but if you can clarify question more then can add more details.
What do you want to achieve? Something like this with CDI:
public class TestClass{
#Inject #Any
Instance<Mapper> mapper;
public void myMethod(){
if(isCat()){
mapper.select(new AnnotationLiteral<Cat>(){}).get();
}
if(isDog()){
mapper.select(new AnnotationLiteral<Dog>(){}).get();
}
}
}
#Dog
public class DogMapper implements Mapper...
#Cat
public class CatMapper implements Mapper...
See the reference documentation: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/pdf/spring-framework-reference.pdf
Pages 43-43 on factory-method in your bean definition.
So I have a number of generics in Spring 3.2 and ideally my architecture would look something like this.
class GenericDao<T>{}
class GenericService<T, T_DAO extends GenericDao<T>>
{
// FAILS
#Autowired
T_DAO;
}
#Component
class Foo{}
#Repository
class FooDao extends GenericDao<Foo>{}
#Service
FooService extends GenericService<Foo, FooDao>{}
Unfortunately with multiple implementations of the generics the autowiring throws an error about multiple matching bean definitions. I assume this is because #Autowired processes before type erasure. Every solution I've found or come up with looks ugly to me or just inexplicably refuses to work. What is the best way around this problem?
How about adding a constructor to the GenericService and move the autowiring to the extending class, e.g.
class GenericService<T, T_DAO extends GenericDao<T>> {
private final T_DAO tDao;
GenericService(T_DAO tDao) {
this.tDao = tDao;
}
}
#Service
FooService extends GenericService<Foo, FooDao> {
#Autowired
FooService(FooDao fooDao) {
super(fooDao);
}
}
Update:
As of Spring 4.0 RC1, it is possible to autowire based on generic type, which means that you can write a generic service like
class GenericService<T, T_DAO extends GenericDao<T>> {
#Autowired
private T_DAO tDao;
}
and create multiple different Spring beans of it like:
#Service
class FooService extends GenericService<Foo, FooDao> {
}
Here is a closest solution. The specialized DAOs are annotated at the business layer. As in the question from OP, the best effort would be having an annotated DAO in the EntityDAO generic template itself. Type erasure seems to be not allowing the specialized type information to get passed onto the spring factories [resulting in reporting matching beans from all the specialized DAOs]
The Generic Entity DAO template
public class EntityDAO<T>
{
#Autowired
SessionFactory factory;
public Session getCurrentSession()
{
return factory.getCurrentSession();
}
public void create(T record)
{
getCurrentSession().save(record);
}
public void update(T record)
{
getCurrentSession().update(record);
}
public void delete(T record)
{
getCurrentSession().delete(record);
}
public void persist(T record)
{
getCurrentSession().saveOrUpdate(record);
}
public T get(Class<T> clazz, Integer id)
{
return (T) getCurrentSession().get(clazz, id);
}
}
The Generic Entity Based Business Layer Template
public abstract class EntityBusinessService<T>
implements Serializable
{
public abstract EntityDAO<T> getDAO();
//Rest of code.
}
An Example Specialized Entity DAO
#Transactional
#Repository
public class UserDAO
extends EntityDAO<User>
{
}
An Example Specialized Entity Business Class
#Transactional
#Service
#Scope("prototype")
public class UserBusinessService
extends EntityBusinessService<User>
{
#Autowired
UserDAO dao;
#Override
public EntityDAO<User> getDAO()
{
return dao;
}
//Rest of code
}
You can remove the #autowire annotation and perform delayed “autowire” using #PostConstruct and ServiceLocatorFactoryBean.
Your GenericService will look similar to this
public class GenericService<T, T_DAO extends GenericDao<T>>{
#Autowired
private DaoLocator daoLocatorFactoryBean;
//No need to autowried, autowireDao() will do this for you
T_DAO dao;
#SuppressWarnings("unchecked")
#PostConstruct
protected void autowireDao(){
//Read the actual class at run time
final Type type;
type = ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[1];
//figure out the class of the fully qualified class name
//this way you can know the bean name to look for
final String typeClass = type.toString();
String daoName = typeClass.substring(typeClass.lastIndexOf('.')+1
,typeClass.length());
daoName = Character.toLowerCase(daoName.charAt(0)) + daoName.substring(1);
this.dao = (T_DAO) daoLocatorFactoryBean.lookup(daoName);
}
daoLocatorFactoryBean does the magic for you.
In order to use it you need to add an interface similar to the one below:
public interface DaoLocator {
public GenericDao<?> lookup(String serviceName);
}
You need to add the following snippet to your applicationContext.xml
<bean id="daoLocatorFactoryBean"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface"
value="org.haim.springframwork.stackoverflow.DaoLocator" />
</bean>
This is a nice trick and it will save you little boilerplate classes.
B.T.W I do not see this boilerplate code as a big issue and the project I working for uses matsev approach.
Why do you want a generic service ? Service classes are meant for specific units of work involving multple entities. You can just inject a repository straight into a controller.
Here is an example of generic repository with constructor argument, you could also make each method Generic instead and have no constructor argument. But each method call would require class as parameter:
public class DomainRepository<T> {
#Resource(name = "sessionFactory")
protected SessionFactory sessionFactory;
public DomainRepository(Class genericType) {
this.genericType = genericType;
}
#Transactional(readOnly = true)
public T get(final long id) {
return (T) sessionFactory.getCurrentSession().get(genericType, id);
}
Example of bean definition for the generic repository - you could have multple different beans, using different contstructor args.
<bean id="tagRepository" class="com.yourcompnay.data.DomainRepository">
<constructor-arg value="com.yourcompnay.domain.Tag"/>
</bean>
Depdncy injection of bean using resource annotation
#Resource(name = "tagRepository")
private DomainRepository<Tag> tagRepository;
And this allows the Domainreposiroty to be subclassed for specific entities/methods, which woul dallow autowiring :
public class PersonRepository extends DomainRepository<Person> {
public PersonRepository(){
super(Person.class);
}
...
You should use autowiring in classes which extends these generics
For this question one needs to understand about what autowire is. In common terms we can say that through autowire we create a object instance/bean at the time of deployment of the web app. So now going with the question if you are declaring autowiring in multiple places with the same name. Then this error comes. Autowiring can be done in multiple ways so if you are using multiple type of autowiring technique, then also one could get this error.
Complete Generic Solution using Spring 4:
Domain Class
#Component
class Foo{
}
#Component
class Bar{
}
DAO Layer
interface GenericDao<T>{
//list of methods
}
class GenericDaoImpl<T> implements GenericDao<T>{
#Autowired
SessionFactory factory;
private Class<T> domainClass; // Get Class Type of <T>
public Session getCurrentSession(){
return factory.getCurrentSession();
}
public DaoImpl() {
this.domainClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), DaoImpl.class);
}
//implementation of methods
}
interface FooDao extends GenericDao<Foo>{
//Define extra methods if required
}
interface BarDao extends GenericDao<Bar>{
//Define extra methods if required
}
#Repository
class FooDao extends GenericDaoImpl<Foo> implements FooDao{
//implementation of extra methods
}
#Repository
class BarDao extends GenericDaoImpl<Bar> implements BarDao{
//implementation of extra methods
}
Service Layer
interface GenericService<T>{
//List of methods
}
class GenericServiceImpl<T> implements GenericService<T>{
#Autowire
protected GenericDao<T> dao; //used to access DAO layer
}
class FooService extends GenericService<Foo>{
//Add extra methods of required
}
class BarService extends GenericService<Bar>{
//Add extra methods of required
}
#Service
class FooServiceImpl extends GenericServiceImpl<Foo> implements GenericService<Foo>{
//implementation of extra methods
}
#Service
class BarServiceImpl extends GenericServiceImpl<Bar> implements GenericService<Bar>{
//implementation of extra methods
}