Tuesday November 04, 2008
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. Posted in Java at Nov 04 2008, 11:39:54 AM MST 13 Comments
Search This Site
Recent Entries
- Raible Road Trip #13
- The good ol' Job Hunt
- How to use GWT 2.0 with Maven and Generate SOYC Reports
- JSON Parsing with JavaScript Overlay Types in GWT
- A Fun Father's Day at Great Sand Dunes
- Going to the Great Sand Dunes for Father's Day
- Implementing OAuth with GWT
- Enhancing Evite.com with GWT and Grails
- 2nd Row at Red Rocks and Elephant Rock Ride
- Creating a Facebook-style Autocomplete with GWT