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.
Related
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)
Use annotation in dao
#Repository("testDao")
public class TestDaoImpl extends JdbcDaoSupport implements BaseDao{
#Override
public Object addObject(String sqlid, Object obj) {
// TODO Auto-generated method stub
return null;
}
Caused by: java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required
I do not want to use :
<bean id="termsDao" class="com.manage.base.dao.impl.TestDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
this code set in xml, and “jdbcTemplate” has been defined in other “spring-xml”。
How to solve this problem by an annotation :“'dataSource' or 'jdbcTemplate' is required”
You can use one of the below approaches. The first one - taking a dataSource is preferred / recommended as you don't expose a SpringFramework class in your public interface. Both will work.
#Repository("testDao")
public class TestDaoImpl extends JdbcDaoSupport implements BaseDao{
#Autowired
TestDaoImpl(DataSource dataSource) {
setDataSource(dataSource);
}
}
Or
#Repository("testDao")
public class TestDaoImpl extends JdbcDaoSupport implements BaseDao{
#Autowired
TestDaoImpl(JDBCTemplate template) {
setJdbcTemplate(template);
}
}
I even feel injecting datasource as a constructor to your DAO is a unnecessary coding step.
Why not inject datasource in Spring config XML into JDBC template and just get jdbctTemplate
object in every DAO.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
and let your DAO extend JDBCSupport class.
public class PersonDao extends JdbcDaoSupport{
public List<Person> selectAll(){
String selectAllSql = "SELECT * FROM PERSON;";
return getJdbcTemplate().query(selectAllSql, new PersonRowMapper());
........
}
}
Full example :
http://www.studytrails.com/frameworks/spring/spring-jdbc-dao-support.jsp
I've created a prototype scoped bean in my application and I'm injecting that to another bean using a setter. But when I'm using the injected bean in my class it is always using the same instance instead of new instance every time.
Here is a snapshot of the code
<bean name="prototypeScope" Class="A" scope="prototype">
</bean>
<bean Class="Consumer">
<property name="a" ref="prototypeScope" />
</bean>
public class Consumer{
privare A a;
public void setA(A a){
this.a = a;
}
public void consume(){
a.doSomething();
}
}
Regards
It is an common mistake related to prototype scoped beans.
A new instance of the prototype scoped bean will be created only when we request a copy of the bean from the application context, not every time we call a method on the instance.
In your case you are injecting the prototype scoped bean to another bean using the setter of the later, so then the second class is created a new instance of the prototype scoped bean will be created. But it will use the same instance as long as it is replace by another instace mannualy by you.
If you want a new instance of the prototype scoped bean during a particular operation like a method call, you have to get a new instance of the bean from the application content.
Ex:
<bean name="prototypeScope" Class="A" scope="prototype">
</bean>
<bean Class="Consumer">
</bean>
Java code:
public class Consumer implements ApplicationContextAware{
privare ApplicationContext context;
public void setApplicationContext(ApplicationContext context){
this.context = context;
}
public void consume(){
A a = context.getBean("prototypeScope", A.class);
a.doSomething();
}
}
In this example when ever the consume method is called a new instance of class A is created.
There are two main ways to deal with the Singleton-Bean-has-Prototype-dependency problem.
One is tight coupling to the applicationContext, as in Ram's answer, the other is Lookup Method Injection.
Basically, you make your bean class abstract and add an abstract method for the dependency, something like this:
public abstract class MyBean{
public abstract MyService lookupService();
}
Then you add a bean definition something like this:
<bean id="myBean" class="fiona.apple.sucks.MyBean">
<!-- sorry, just wanted to insert sucks after Spring's fiona apple example,
didn't think about the connotations :-) -->
<lookup-method name="lookupService"/>
</bean>
Now Spring will create a CGLib subclass of your bean class that will return a new Prototype instance for every time you call myBean.lookupService().
I used such approach once..
First I declared a bean
<bean id="notSingelton" class="com.Foo" singleton="false" />
Then made an interface
public interface FooFactory {
Foo make(String name);
}
wrapped it into ServiceLocatorFactoryBean
<bean id="fooFactory"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface" value="com.FooFactory" />
</bean>
<bean id="consumer" class="com.Consumer">
<constructor-arg ref="fooFactory" />
</bean>
And consumer class looked something like that:
public class Consumer {
private FooFactory fooFactory;
public Consumer(FooFactory fooFactory) {
this.fooFactory = fooFactory;
}
public void consume(){
Foo foo = fooFactory.make("notSingelton");
foo.doSomething();
}
}
One of the strongest accents of the Spring framework is the Dependency Injection concept. I understand one of the advices behind that is to separate general high-level mechanism from low-level details (as announced by Dependency Inversion Principle).
Technically, that boils down to having a bean implementation to know as little as possible about a bean being injected as a dependency, e.g.
public class PrintOutBean {
private LogicBean logicBean;
public void action() {
System.out.println(logicBean.humanReadableDetails());
}
//...
}
<bean class="PrintOutBean">
<property name="loginBean" ref="ShoppingCartBean"/>
</bean>
But what if I wanted to a have a high-level mechanism operating on multiple dependent beans?
public class MenuManagementBean {
private Collection<Option> options;
public void printOut() {
for (Option option:options) {
// do something for option
}
//...
}
}
I know one solution would be to use #Autowired annotation in the singleton bean, that is...
#Autowired
private Collection<Option> options;
But doesn't it violate the separation principle? Why do I have to specify what dependents to take in the very same place I use them (i.e. MenuManagementBean class in my example)?
Is there a way to inject collections of beans in the XML configuration like this (without any annotation in the MMB class)?
<bean class="MenuManagementBean">
<property name="options">
<xxx:autowire by-type="MyOptionImpl"/>
</property>
</bean>
Old question and in Spring 3.1 it is possible:
public class PluginPrototypeTest extends ASpringWebTest {
#Autowired
Collection<IDummyRepo> repos;
#Test
public void cacheTest() {
assertNotNull(repos);
assertEquals(2, repos.size());
for(IDummyRepo r: repos){
System.out.println(r.getName());
}
}
}
#Repository
public class DummyRepo implements IDummyRepo {
#Override
public String getName(){
return "DummyRepo";
}
}
#Repository
public class DummyRepo2 implements IDummyRepo {
#Override
public String getName(){
return "DummyRepo2";
}
}
There's no out-of-the-box facility to do this, no. However, if you want a way of collecting all beans of a given type into a collection, without using an #Autowired list, then it's easy to write a custom FactoryBean to do it for you:
public class BeanListFactoryBean<T> extends AbstractFactoryBean<Collection<T>> {
private Class<T> beanType;
private #Autowired ListableBeanFactory beanFactory;
#Required
public void setBeanType(Class<T> beanType) {
this.beanType = beanType;
}
#Override
protected Collection<T> createInstance() throws Exception {
return beanFactory.getBeansOfType(beanType).values();
}
#Override
public Class<?> getObjectType() {
return Collection.class;
}
}
and then
<bean class="MenuManagementBean">
<property name="options">
<bean class="BeanListFactoryBean">
<property name="beanType" class="MyOptionImpl.class"/>
</bean>
</property>
</bean>
However, this all seems like a lot of effort to avoid putting #Autowired in your original class. It's not much of a violation of SoC, if it is at all - there's no compiltime dependency, and no knowledge of where the options are coming from.
Alternative to #Autowired, using a context file: http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire
So you'd have:
<bean class="MenuManagementBean" autowire="byType" />
Other properties can be specified, as normal, and that would override the autowiring only for those properties.
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;