Moving from Spring's XML to Annotations in AppFuse
Last night, I did a spike on AppFuse to change XML to Spring annotations (@Repository, @Service and @Autowired) in its service and data modules. While I was able to accomplish everything in a few hours (including converting tests), I did run into a couple issues.
AbstractTransactionalJUnit4..Tests vs. AbstractTransactionalDataSource..Tests
I've switched from my favorite Spring class to the annotation-happy AbstractTransactionalJUnit4SpringContextTests. However, this has presented an issue: when using ATDSSCT, I was able to call endTransaction() and startNewTransaction(). With ATJ4SCT, this doesn't seem possible. Below is a screenshot of the diff on a test method in the JPA implementation of UserDaoTest:
On the right, you'll notice that I had to comment out @ExpectedException to get the test to pass. This concerns me since this exception should be thrown. Is there a way to call endTransaction() and startNewTransaction() when subclassing AbstractTransactionalJUnit4SpringContextTests?
Instantiating GenericDao Implementations Programmatically
The second feature I tried to add is the ability to instantiate a GenericDao programatically rather than requiring a XML bean definition. In current versions of AppFuse, you can use the following bean definition to create a GenericDao for a model object.
<bean id="personDao" class="org.appfuse.dao.hibernate.GenericDaoHibernate">
<constructor-arg value="org.appfuse.tutorial.model.Person"/>
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
When moving to a no-XML required architecture, it'd be nice to allow users to create GenericDao's programmatically. Below is the easiest way I've found to do this in a test:
GenericDao<User, Long> genericDao;
@Autowired
SessionFactory sessionFactory;
@Before
public void setUp() {
genericDao = new GenericDaoHibernate<User, Long>(User.class);
genericDao.setSessionFactory(sessionFactory);
}
However, there's a couple problems with this. First of all, mixing constructor injection and setter injection probably isn't a good idea. Changing the constructor to take a SessionFactory solves this problem, but now all subclasses need to have a more verbose constructor:
@Autowired
public UserDaoHibernate(SessionFactory sessionFactory) {
super(User.class, sessionFactory);
}
Whereas before they had:
public UserDaoHibernate() {
super(User.class);
}
In an ideal world, I could call new GenericDaoHibernate<User, Long>(User.class) and the SessionFactory would be wired in auto-magically. Is this possible with Spring 2.5?
The 2nd problem this presents is your client code will now be dependent on an implementation rather than the interface. I don't know how to solve that one, but I'd love to figure out a way to create GenericDaos with no XML and no implementation details in the client. Any ideas are most welcome.
If you'd like to see all the changes I made in converting from XML to Annotations, please see this patch.






In a few weeks, I'm heading to the