I came across this useful Util class provided by Apache Commons Collections.
ComparatorUtils
one of the useful methods here is chainedComparator which allows us to chain comparators to achieve sorting on multiple attributes of an object.
if the results from the first comparator result in 0 then the next comparator is invoked.
I remember writing a Util for myself for the same. But This class is much more robust and accessible.
I guess this is a page to share all issues I have troubleshooted and found interesting enough to share. Also a place to give back something , in return of all the help I have received or taken from forums.
Showing posts with label multiple daos. Show all posts
Showing posts with label multiple daos. Show all posts
Monday, 21 June 2010
Apache Commons Collections - Chaining Comparators
Labels:
apache,
chain,
collections,
comparator,
multiple daos,
util
Thursday, 18 March 2010
Unit Testing with multiple daos - AbstractTransactionalDataSourceSpringContextTests
I had a scenario where I wanted to unit test my dao methods , however some of the daos depended on data being provided from other daos to run successfully.
In order to achieve the same I required to be able to configure multiple data sources in my spring config and inject the data sources as and when required.
I used AbstractTransactionalDataSourceSpringContextTests for my Junit test cases.
And my spring config xml looked like :
<!-- Database 1-->
<bean id="testDataSource1" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
</bean>
<!-- Database 2 -->
<bean id="testDataSource2" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
</bean>
<bean id="dao1" class="Dao1Impl">
<property name="dataSource" ref="testDataSource1">
</property></bean>
<bean id="dao2" class="Dao2Impl">
<property name="dataSource" ref="testDataSource2">
</property></bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="testDataSource1">
</property></bean>
When I re ran the unit test . I came across the following error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DaoTest': Unsatisfied dependency expressed through bean property 'dataSource': No unique bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 2: [testDataSource1, testDataSource2]
I had to change my unit test so that it looked like below:
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
public abstract class BaseTest extends AbstractTransactionalDataSourceSpringContextTests {
@Autowired
Dao1 dao1;
@Autowired
Dao2 dao2;
@Autowired
DataSource testDataSource1;
@Autowired
DataSource testDataSource2;
/* (non-Javadoc)
* @see org.springframework.test.AbstractSingleSpringContextTests#getConfigPath()
*/
@Override
protected String getConfigPath() {
return "spring-test-config.xml";
}
@Override
@Autowired
public void setDataSource(@Qualifier("testDataSource1") final DataSource dataSource){
super.setDataSource(dataSource);
}
/**
* @return the dao1
*/
public Dao1 getDao1() {
return dao1;
}
/**
* @param dao1 the dao1 to set
*/
public void setDao1(Dao1 dao1) {
this.dao1 = dao1;
}
/**
* @return the dao2
*/
public Dao2 getDao2() {
return dao2;
}
/**
* @param dao2 the dao2 to set
*/
public void setDao2(Dao2 dao2) {
this.dao2 = dao2;
}
/**
* @return the testDataSource1
*/
public DataSource getTestDataSource1() {
return testDataSource1;
}
/**
* @param testDataSource1 the testDataSource1 to set
*/
public void setTestDataSource1(@Qualifier("testDataSource1") DataSource testDataSource1) {
this.testDataSource1 = testDataSource1;
}
/**
* @return the testDataSource2
*/
public DataSource getTestDataSource2() {
return testDataSource2;
}
/**
* @param testDataSource2 the testDataSource2 to set
*/
public void setTestDataSource2(@Qualifier("testDataSource2") DataSource testDataSource2) {
this.testDataSource2 = testDataSource2;
}
}
the interesting thing above is the @Qualifier annotation which allows us to reference which data sources to inject while initializing the beans.
Now while writing my test cases I can simply switch between the datasources like :
setDataSource(getTestDataSource2());
// Perform transaction related to data source 2
setDataSource(getTestDataSource1());
// Set the data source back to the main data source
I know Unit test cases must be independent , and should be testing on real time data , however if in case a need arises to be able to test the same without having to worry about re deploying and re starting application servers , this method is useful.
In order to achieve the same I required to be able to configure multiple data sources in my spring config and inject the data sources as and when required.
I used AbstractTransactionalDataSourceSpringContextTests for my Junit test cases.
And my spring config xml looked like :
<!-- Database 1-->
<bean id="testDataSource1" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
</bean>
<!-- Database 2 -->
<bean id="testDataSource2" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
</bean>
<bean id="dao1" class="Dao1Impl">
<property name="dataSource" ref="testDataSource1">
</property></bean>
<bean id="dao2" class="Dao2Impl">
<property name="dataSource" ref="testDataSource2">
</property></bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="testDataSource1">
</property></bean>
When I re ran the unit test . I came across the following error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DaoTest': Unsatisfied dependency expressed through bean property 'dataSource': No unique bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 2: [testDataSource1, testDataSource2]
I had to change my unit test so that it looked like below:
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
public abstract class BaseTest extends AbstractTransactionalDataSourceSpringContextTests {
@Autowired
Dao1 dao1;
@Autowired
Dao2 dao2;
@Autowired
DataSource testDataSource1;
@Autowired
DataSource testDataSource2;
/* (non-Javadoc)
* @see org.springframework.test.AbstractSingleSpringContextTests#getConfigPath()
*/
@Override
protected String getConfigPath() {
return "spring-test-config.xml";
}
@Override
@Autowired
public void setDataSource(@Qualifier("testDataSource1") final DataSource dataSource){
super.setDataSource(dataSource);
}
/**
* @return the dao1
*/
public Dao1 getDao1() {
return dao1;
}
/**
* @param dao1 the dao1 to set
*/
public void setDao1(Dao1 dao1) {
this.dao1 = dao1;
}
/**
* @return the dao2
*/
public Dao2 getDao2() {
return dao2;
}
/**
* @param dao2 the dao2 to set
*/
public void setDao2(Dao2 dao2) {
this.dao2 = dao2;
}
/**
* @return the testDataSource1
*/
public DataSource getTestDataSource1() {
return testDataSource1;
}
/**
* @param testDataSource1 the testDataSource1 to set
*/
public void setTestDataSource1(@Qualifier("testDataSource1") DataSource testDataSource1) {
this.testDataSource1 = testDataSource1;
}
/**
* @return the testDataSource2
*/
public DataSource getTestDataSource2() {
return testDataSource2;
}
/**
* @param testDataSource2 the testDataSource2 to set
*/
public void setTestDataSource2(@Qualifier("testDataSource2") DataSource testDataSource2) {
this.testDataSource2 = testDataSource2;
}
}
the interesting thing above is the @Qualifier annotation which allows us to reference which data sources to inject while initializing the beans.
Now while writing my test cases I can simply switch between the datasources like :
setDataSource(getTestDataSource2());
// Perform transaction related to data source 2
setDataSource(getTestDataSource1());
// Set the data source back to the main data source
I know Unit test cases must be independent , and should be testing on real time data , however if in case a need arises to be able to test the same without having to worry about re deploying and re starting application servers , this method is useful.
Labels:
annotations,
autowire,
multiple daos,
multiple datasources,
qualifier,
spring,
unit . test
Subscribe to:
Posts (Atom)