Spring wire inherited property [duplicate] - java

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

Related

How to Autowire a 1-arg Object Constructor with Previously Autowired Object?

Given the following MyConstructorClass:
#Component
public class MyConstructorClass{
MyObj var;
public MyConstructorClass( MyObj constrArg ){
this.var = var;
}
...
}
How can I autowire a field that requires a constructor argument from a previously #Autowired field? Below is an example.
Note - this question, I believe, is similar to this one, except that my constructor argument is not a String. This code sample is slightly modified from this question.
#Service
public class MyBeanService{
#Autowired
CustomObject customObj; // no arguments to constructor
#Autowired
MyConstructorClass myConstructorClass; // requires `customObj` as an argument
....
}
How can I modify MyBeanService to properly construct myConstructorClass with customObj?
You just need to annotated the constructor of MyConstructorClass with #Autowired:
#Component
public class MyConstructorClass {
final private CustomObject customObj;
#Autowired
public MyConstructorClass(CustomObject customObj) {
this.customObj = customObj;
}
}
Another alternative, (without adding the #Autowired constructor to MyConstructorClass) is to use a #Configuration bean:
#Configuration
public class MyConfiguration {
#Bean
public CustomObject customObj() {
return customObj;
}
#Bean
public MyConstructorClass myConstructorClass() {
return new MyConstructorClass(customObj());
}
#Bean
public MyBeanService myBeanService() {
return new MyBeanService();
}
}
you can use the <constructor-arg> in your servlet
<bean id="myConstructorClass" class="package.MyConstructorClass">
<constructor-arg>
<bean class="package.CustomObject"/>
</constructor-arg>
</bean>
If this is the only place you need to use that class could use #PostConstruct to instantiate itself. I think there is a better solution, but this is off the top of my head.
#Service
public class MyBeanService{
#Autowired
CustomObject customObj;
MyConstructorClass myConstructorClass;
#PostConstruct
public void construct()
{
myConstructorClass = new MyConstructorClass(customObj);
}
}
In the constructor, you can refer to other beans defined in Spring.
<bean id="myConstructorClass" class="package.MyConstructorClass">
<constructor-arg index="0" ref="customObj"/>
</bean>

Spring Annotation : Converting XML Configuration to Annotation

I am using xml configuration in my Spring Application. Now i would like to convert the existing classes to use annotation(like #service, #Repository etc) instead of xml configuration.
Business Logic(Irrelevant for this question, just for understanding):
Sevice connnects to Americas database and find the skus(products) and deactivates the skus.
Sevice connnects to EMEA database and find the skus(products) and deactivates the skus.
Here is the sample code.
/* Service code, which has 2 instances of SkuDAO, one connecting to US database and one connecting to EMEA database */
public class DeactivationService {
private static final Logger LOG = Logger.getLogger(DeactivationService.class);
private SkuDAO amerdao; //Dependency Injection Amer
private SkuDAO emeadao; //Dependency Injection EMEA
public DeactivationService(SkuDAO amerdao,SkuDAO emeadao) {
this.amerdao=amerdao;
this.emeadao=emeadao;
}
/*
* Step 1: find inactive sku in americas skudao1.find()
* Step 2: find inactive sku in emea skudao2.find()
* Step 3: deactivate sku in americas
* Step 4: deactivate sku in emea
*/
public void deactivateSku() {
List<Sku> totalList = new ArrayList<Sku>();
List<Sku> amerList = amerdao.find();
List<Sku> emeaList = emeadao.find();
amerdao.deactivate(amerList);
emeaList.deactivate(emeaList);
}
}
/* DAO interface */
public interface SkuDAO {
public List<Sku> find();
public void deactivate(List<Sku>);
}
/* DAO Implementation
Here one constructor in which DataSource is injected
*/
public class SkuDAOImpl implements SkuDAO {
private DataSource datasource; //Dependency injection
private JdbcTemplate jdbcTemplate;
public SkuDAOImpl(DataSource datasource) {
this.datasource=datasource;
}
public List<Sku> find() {
//some processing to find the sku, purposely left empty as it is a sample code
}
public void deactivate(List<Sku>) {
//some processing to deactivate the sku, purposely left empty as it is a sample code
}
}
Spring Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:property-placeholder location="file:${dbconfiguration}"/>
<bean id="AmericasDataSource" class="dell.harmony.data.HarmonyBasicDataSource" destroy-method="close" >
<property name="url"><value>${HarmonyAmericasDb.url}</value></property>
<property name="driverClassName"><value>${HarmonyAmericasDb.driverClassName}</value></property>
<property name="username"><value>${HarmonyAmericasDb.username}</value></property>
<property name="password"><value>${HarmonyAmericasDb.password}</value></property>
<property name="initialSize"><value>${HarmonyAmericasDb.initialSize}</value></property>
<property name="maxActive"><value>${HarmonyAmericasDb.maxActive}</value></property>
<property name="maxWait"><value>${HarmonyAmericasDb.maxWait}</value></property>
<property name="maxIdle"><value>${HarmonyAmericasDb.maxIdle}</value></property>
<property name="minIdle"><value>${HarmonyAmericasDb.minIdle}</value></property>
<property name="removeAbandoned"><value>${HarmonyAmericasDb.removeAbandoned}</value></property>
<property name="removeAbandonedTimeout"><value>${HarmonyAmericasDb.removeAbandonedTimeout}</value></property>
</bean>
<bean id="EMEADataSource" class="dell.harmony.data.HarmonyBasicDataSource" destroy-method="close" >
<property name="url"><value>${HarmonyEMEADb.url}</value></property>
<property name="driverClassName"><value>${HarmonyEMEADb.driverClassName}</value></property>
<property name="username"><value>${HarmonyEMEADb.username}</value></property>
<property name="password"><value>${HarmonyEMEADb.password}</value></property>
<property name="initialSize"><value>${HarmonyEMEADb.initialSize}</value></property>
<property name="maxActive"><value>${HarmonyEMEADb.maxActive}</value></property>
<property name="maxWait"><value>${HarmonyEMEADb.maxWait}</value></property>
<property name="maxIdle"><value>${HarmonyEMEADb.maxIdle}</value></property>
<property name="minIdle"><value>${HarmonyEMEADb.minIdle}</value></property>
<property name="removeAbandoned"><value>${HarmonyEMEADb.removeAbandoned}</value></property>
<property name="removeAbandonedTimeout"><value>${HarmonyEMEADb.removeAbandonedTimeout}</value></property>
</bean>
**<!-- Sku Deactivation -->**
<bean id="SkuAmerDao" class="dell.harmony.service.skudeactivation.dao.SkuDAOImpl">
<constructor-arg index="0"><ref bean="AmericasDataSource"/></constructor-arg>
</bean>
<bean id="SkuEMEADao" class="dell.harmony.service.skudeactivation.dao.SkuDAOImpl">
<constructor-arg index="0"><ref bean="EMEADataSource"/></constructor-arg>
</bean>
<bean id="ServiceManager" class="dell.harmony.service.skudeactivation.service.DeactivationService">
<constructor-arg index="0"><ref bean="SkuAmerDao"/></constructor-arg>
<constructor-arg index="1"><ref bean="SkuEMEADao"/></constructor-arg>
</bean>
</beans>
Now i want to convert the above classes to highlighted inside xml("Sku Deactivation") , into annodation.
My code for convertion is as follows:
#Service
public class DeactivationService {
private static final Logger LOG = Logger.getLogger(DeactivationService.class);
private SkuDAO amerdao; //Dependency Injection Amer
private SkuDAO emeadao; //Dependency Injection EMEA
#Autowired(required=true)
public DeactivationService( #Qualifier("SkuAmerDao") SkuDAO amerdao, #Qualifier("SkuEMEADao") SkuDAO emeadao) {
this.amerdao=amerdao;
this.emeadao=emeadao;
}
}
In the above constructor, now 'amerdao' instance, should be injected with AmericasDataSource and 'emeadao' with EMEADataSource, how to do that?
Please note, i dont have a setter in the SkuDAOImpl. Also there is only one datasource instance inside the SkuDAOImpl.
can you given sample code of SkuDAOImpl with annodation.
Any suggestion, to improve the coding from service to dao , if it can be done in a better way. (Not required to answer this)
EDITED NOW: just to be clear with question 1, I would like to remove the below two lines in Spring xml and use annotation instead my DeactivationService. Is it possible?
<bean id="SkuAmerDao" class="dell.harmony.service.skudeactivation.dao.SkuDAOImpl">
<constructor-arg index="0"><ref bean="AmericasDataSource"/></constructor-arg>
</bean>
<bean id="SkuEMEADao" class="dell.harmony.service.skudeactivation.dao.SkuDAOImpl">
<constructor-arg index="0"><ref bean="EMEADataSource"/></constructor-arg>
</bean>
What about:
#Service
public class DeactivationService {
private static final Logger LOG = Logger.getLogger(DeactivationService.class);
#Autowired
#Qualifier("SkuAmerDao")
private SkuDAO amerdao; //Dependency Injection Amer
#Autowired
#Qualifier("SkuEMEADao")
private SkuDAO emeadao; //Dependency Injection EMEA
// no constructor needed.
}
public abstract class BaseDao implements SkuDAO {
private final JdbcTemplate jdbcTemplate;
protected BaseDao() {
this.jdbcTemplate = new JdbcTemplate(getDataSource());
}
protected abstract DataSource getDataSource();
public List<Sku> find() {
//some processing to find the sku, purposely left empty as it is a sample code
}
public void deactivate(List<Sku>) {
//some processing to deactivate the sku, purposely left empty as it is a sample code
}
}
#Repository("SkuAmerDao")
public class SkuAmerDAOImpl extends BaseDao {
#Autowired
#Qualifier("AmericasDataSource")
private DataSource datasource; //Dependency injection
#Override
protected DataSource getDatasource() {
return dataSource;
}
}
#Repository("SkuEMEADao")
public class SkuEMEADAOImpl extends BaseDao {
#Autowired
#Qualifier("EMEADataSource")
private DataSource datasource; //Dependency injection
#Override
protected DataSource getDatasource() {
return dataSource;
}
}
Always the same principle:
class is made a bean by an annotation #Service, #Component, #Repository (those annotations can take the name of the bean as value)
injection of dependency is made on fields with #Autowired and if there are more than one corresponding bean (in your case you have two DataSources), add a #Qualifier to specify which one.
Full documentation here.

Spring Test mock one dependency

Suppose I have these two parts of XML Spring config in two distinct files;
//daoContext.xml
<bean id="myDao" class="com.MyDao"/>
//logicContext.xml
<bean id="myLogic" class="com.MyLogic">
<constructor-arg ref="myDao"/><!--or other type of injection--?
</bean>
And there is the test class:
#ContextConfiguration("logicContext.xml")
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
#Autowired
private MyLogic myLogic;
#Test
public void testMyTestable() {
//...
}
}
Now, what I want is to be able to mock MyDao class and inject is somehow into MyLogic which is to be injected in BaseLogicTest so I can use MyLogic with a mocked MyDao. Is this possible using Spring/Spring Test?
The simplest solution is load all your xml. And manually replace dependence in test case.
#ContextConfiguration("logicContext.xml")
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
#Autowired
private MyLogic myLogic;
#Before
public void injectTestDoubles() {
myLogic.setMyDao(...);
}
#DirtiesContext
#Test ...//test methods
}
But this corrupts the application context, so you need #DirtiesContext if you need "real" myDao in other test case sharing the same application context.
The most popular solution (my personal opinion :P ) is using mockito and a test-specific xml.
//daoContext.xml
<bean id="myDao" class="com.MyDao"/>
//logicContext.xml
<bean id="myLogic" class="com.MyLogic">
<constructor-arg ref="myDao"/><!--or other type of injection--?
</bean>
//test-logicContext.xml
<bean id="myDao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.MyDao" />
</bean>
#ContextConfiguration({"logicContext.xml", "test-logicContext.xml"})
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
#Autowired
private MyLogic myLogic;
#Autowired
private MyDao myDao;//retrieve mock so you could define expectations
#Test //test methods
#After public void clearMocks() {
Mockito.reset(myDao);//this is important if you have several test methods
}
}
And this solution works for other mock framework like easyMock.
You can do this by creating a FactoryBean to create the MyDao (or any) mock to be injected into your MyLogic instance.
public class FactoryBeanForMocks<T> implements FactoryBean<T> {
private Class<T> mockClass;
public FactoryBeanForMocks(Class<T> mockClass) {
super();
this.mockClass = mockClass;
}
#Override
public T getObject() throws Exception {
return Mockito.mock(mockClass);
}
#Override
public Class<?> getObjectType() {
return mockClass;
}
#Override
public boolean isSingleton() {
return true;
}
}
Make the factory bean entry into your logicContext.xml so that a mock of MyDao can be injected into MyLogic:
//logicContext.xml
<bean id="myLogic" class="com.MyLogic">
<constructor-arg ref="myDao"/><!--or other type of injection--?
</bean>
<bean id="myDao" class="x.y.z.FactoryBeanForMocks">
<constructor-arg name="mockClass" value="x.y.MyDao"></constructor-arg>
</bean>
And this is your test class:
#ContextConfiguration("logicContext.xml")
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
#Autowired
private MyLogic myLogic;
//You can inject the mock myDao into it so that you can stub/verify method calls on it
#Autowired
private MyDao myDao;
#Test
public void testMyTestable() {
//...
when(myDao.process()).thenReturn("a");//stubbing myDao.process()
assertEquals("a", myLogic.processRequest());// assuming myLogic.processRequest() calls myDao.process()
}
}

What is meant by abstract="true" in spring?

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.

How to collect and inject all beans of a given type in Spring XML configuration

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.

Categories

Resources