I want to create beans based on a specific type. Ive an abstract class which is extended by two concrete classes whose object I want to instantiate via a Factory (or any other best suited approach) class based on the type.
public abstract class Helper{
public abstract boolean check();
}
public class C1 extends Helper{
public boolean check(){
//implementation here
}
}
public class C2 extends Helper{
public boolean check(){
//implementation here
}
}
public interface MyFactory{
public Helper create(){
}
application-context.xml
<bean id=.../>
How should I do this using dependency injection of Spring via XML?
Also, I tried ServiceLocatorFactoryBean approach but that does not help me pass the object of required type. Followed this link - http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
Implement your factory (for example MyFactoryImpl) and then configure:
<bean id="myFactoryImpl" class="com.example.MyFactoryImpl" />
<bean id="c1"
factory-bean="myFactoryImpl"
factory-method="create"/>
example factory:
public class com.example.MyFactoryImpl implements MyFactory {
public Helper create(){return new C1()}
}
(Spring does not require that MyFactory interface)
Related
I have an abstract class, which has many classes extending it. The abstract class has a field used by all the child classes. The field needs to be injected using guice.
public abstract class StrategyClass {
#Inject
ClassTobeInjected variableName;
}
I have a provider written for injecting this, which has a provider and a singleton:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
final AppConfigBinder appConfigBinder = new AppConfigBinder(binder());
appConfigBinder.bindPrefix("*");
}
#Provider
#Singleton
public ClassTobeInjected getfield() {
return new Instance of ClassTobeInjected;
}
}
I see that the provider is creating an instance. However the abstract class field is always null. Do I need to add anything in the configure of my module? Is there something I am missing?
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
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
}
Abstract classes cannot be instantiated in java. But spring says something like bean creation with abstract="true". If a state of an abstract class is initialised only by its child class instance(i guess i am right), then if i need to use that attribute inside the method which is defined in the abstract class then... is there a possibility for it? I have a set of code as follows:
class abstract A {
private Something somethingObj;
// getters and setters are present.
public void logSomething() {
try{
//some code which throws exception
}
catch(Exception e){
somethingObj.logIt(e);// I have some logic inlogIt method.
}
}
}
Abstract beans in Spring are somewhat different from abstract classes. In fact, abstract bean in Spring doesn't even have to be mapped to any class. Take this as an example:
<bean id="dao" abstract="true">
<property name="dataSource" ref="dataSource"/>
<property name="someHelper" ref="someHelper"/>
</bean>
<bean id="fooDao" class="FooDao" parent="dao">
<property name="fooHelper" ref="fooHelper"/>
</bean>
<bean id="barDao" class="BarDao" parent="dao">
<property name="barHelper" ref="barHelper"/>
</bean>
And classes:
public class FooDao {
private DataSource dataSource;
private SomeHelper someHelper;
private FooHelper fooHelper;
//setters
}
public class BarDao {
private DataSource dataSource;
private SomeHelper someHelper;
private BarHelper barHelper;
//setters
}
Note that FooDao and BarDao do not have any parent (abstract or not) base class in common. Parent abstract bean definition is used only to group common properties, so you avoid repetition in XML.
On the other hand introducing abstract Dao class that both FooDao and BarDao inherit from would be a good idea:
public abstract Dao {
protected DataSource dataSource;
protected SomeHelper someHelper;
//setters
}
public class FooDao extends Dao {
private FooHelper fooHelper;
//setters
}
public class BarDao extends Dao {
private BarHelper barHelper;
//setters
}
But still dao bean doesn't have to define a class. Treat abstract beans as a way to reduce duplication in XML when several concrete beans have same dependencies.
Actually, abstract parent bean is not necessary to define class attribute, you may just need a common property for sharing.
According to this tutorial
The parent bean cannot be instantiated on its own because it is
incomplete, and it is also explicitly marked as abstract. When a
definition is abstract like this, it is usable only as a pure template
bean definition that serves as a parent definition for child
definitions.
This question already has answers here:
How to Autowire Bean of generic type <T> in Spring?
(6 answers)
Closed 5 years ago.
I'm trying to use Spring IoC with an interface like this:
public interface ISimpleService<T> {
void someOp(T t);
T otherOp();
}
Can Spring provide IoC based on the generic type argument T? I mean, something like this:
public class SpringIocTest {
#Autowired
ISimpleService<Long> longSvc;
#Autowired
ISimpleService<String> strSvc;
//...
}
Of course, my example above does not work:
expected single matching bean but found 2: [serviceLong, serviceString]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:243)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:957)
My Question: is it possible to provide a similar functionality with minimum modifications to either the Interface or the implementing classes? I know for instance I can use #Qualifiers, but I want to keep things as simple as possible.
I do not believe this is possible due to erasure. We generally switched to strongly typed sub-interfaces when going for full-autowiring:
public interface LongService extends ISimpleService<Long> {}
public interface StringService extends ISimpleService<String> {}
Upon doing this switch we found we actually liked this pretty well, because it allows us to do "find usage" tracking much better, something you loose with the generics interfaces.
i don't think thats possible without Qualifier
ill try to show my Solutions with a genericDAO, sorry if it's a bit detailed
the Interface and Implementation Class Definition
public interface GenericDAO<T, ID extends Serializable> (...)
public class GenericDAOImpl<T, ID extends Serializable>
implements GenericDAO<T, ID>
(...) important is this constructor
public GenericDAOImpl(Class<T> persistentClass) {
this.persistentClass = persistentClass;
}
the spring bean definition, notice the abstract="true"
<bean id="genericHibernateDAO" class="de.optimum24.av.pers.ext.hibernate.dao.GenericDAOImpl"
abstract="true">
<description>
<![CDATA[
Definition des GenericDAO.
]]>
</description>
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Using this genericDAO without special implementation Class
<bean id="testHibernateChildDao" class="de.optimum24.av.pers.ext.hibernate.dao.GenericDAOImpl">
<property name="sessionFactory" ref="sessionFactory" />
<constructor-arg>
<value>de.optimum24.av.pers.test.hibernate.domain.TOChild</value>
</constructor-arg>
</bean>
notice the constructor-arg with an concrete Class, if you work with Spring Annotation you need to do:
#Autowired
#Qualifier(value = "testHibernateChildDao")
private GenericDAO<TOChild, Integer> ToChildDAO;
to distinguish the various versions of genericDao Beans (notice the Qualifier with direct Reference to the Beanname)
Using this genericDAO with special implementation Class
the Interface and Class
public interface TestHibernateParentDAO extends GenericDAO<TOParent, Integer>{
void foo();
}
public class TestHibernateParentDAOImpl extends GenericDAOImpl<TOParent, Integer>
implements TestHibernateParentDAO {
#Override
public void foo() {
//* no-op */
}
}
the Bean Definition, notice the "parent" Reference to the abstract genericDAO above
<bean id="testHibernateParentDao" class="de.optimum24.av.pers.test.hibernate.dao.TestHibernateParentDAOImpl"
parent="genericHibernateDAO" />
and usage with Spring Annotation
#Autowired
private TestHibernateParentDAO ToParentDAO;
It is possible to do this with erasure, if the generic type is fully reified at compile-time. In this case the type information is available via either of:
Class#getGenericInterfaces()
Class#getGenericSuperclass()
This is the major feature of Guice which is missing from Spring.
Don't make your interface generic. Make your methods, instead:
public interface ISimpleService {
public <T> T doSomething(T param);
}
Hope it helps.
When doing this with certain persistence layers, Spring Data does this for you. Spring Data is a really great time-saving and simplification tool if you are using JPA, or Neo4j, or MongoDB, or something else that it supports.
Another option is to annotate the interface implementing bean with name on one side and to annotate with qualifier pointing to created name on the other side :) Here is a quick example I am using in my project :
public interface IDAO<T> {
public void insert(T model);
public void update(T model);
public void delete(T model);
}
Abstract class as predecessor :
public abstract class AbstractHibernateDAO {
protected SessionFactory sessionFactory;
protected Session currentSession() {
return sessionFactory.getCurrentSession();
}
}
Implementation of abstract class for entity user:
#Repository(value = "userRepository")
public class UserDAO extends AbstractHibernateDAO implements IDAO<User> {
#Autowired
public UserDAO(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
public void insert(User user) {
currentSession().save(user);
}
#Override
public void update(User user) {
currentSession().update(user);
}
#Override
public void delete(User user) {
currentSession().delete(user);
}
}
And finally injecting right implementation:
#Resource
#Qualifier(value = "userRepository")
IDAO<User> userPersistence;