Matt Raible has been building web applications for most of his adult life. He started tinkering with the web before Netscape 1.0 was even released. For the last 16 years, Matt has helped companies adopt open source technologies (Spring, Hibernate, Apache, Struts, Tapestry, Grails) and use them effectively. Matt has been a speaker at many conferences worldwide, including Devoxx, Jfokus, ÜberConf, No Fluff Just Stuff, and a host of others.

Matt is a DZone MVB and is not an employee of DZone and has posted 142 posts at DZone. You can read more from them at their website. View Full User Profile

Moving from Spring's XML to Annotations in AppFuse

11.05.2008
| 12724 views |
  • submit to reddit

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:

AbstractTransactionalJUnit4SpringContextTests vs. AbstractTransactionalDataSourceSpringContextTests

 

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.

From http://raibledesigns.com/rd/entry/moving_from_spring_s_xml

Published at DZone with permission of Matt Raible, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Mike Funk replied on Wed, 2008/11/05 - 10:25am

Consider building a true generic entity manager (just one class) that is autowired with a hibernate template. Then autowire your generic entity manager into any service, and use transactional annotations as required. No more daos.

 

Jonathan Curran replied on Wed, 2008/11/05 - 12:36pm in response to: Mike Funk

An example (article) would be great :)

Mike Funk replied on Thu, 2008/11/06 - 12:20pm in response to: Jonathan Curran

Hopefully, this will help:

1. Create a generic spring-hibernate entity manager:

@Repository
public class HibernateGenericEntityManager {
    @Autowired private HibernateTemplate hibernateTemplate;

    public HibernateGenericEntityManager() {
    }

    public Object execute(HibernateCallback callback) {
        return hibernateTemplate.execute(callback);
    }

    public <E> void save(E entity) {
        hibernateTemplate.saveOrUpdate(entity);
    }

   public <E> void save(Collection<E> entities) {
        hibernateTemplate.saveOrUpdateAll(entities);
    }

    public <E> void delete(E entity) {
        hibernateTemplate.delete(entity);
    }

    public void delete(Class type, Serializable key) {
        delete(find(type, key));
    }

    @SuppressWarnings("unchecked")
    public <E> E find(Class type, Serializable id) {
        return (E) hibernateTemplate.load(type, id);
    }

   @SuppressWarnings("unchecked")
    public <E> List<E> list(Class type) {
        return (List<E>) hibernateTemplate.loadAll(type);
    }

    @SuppressWarnings("unchecked")
    public <E> List<E> query(String namedQuery) {
        return hibernateTemplate.findByNamedQuery(namedQuery);
    }

    @SuppressWarnings("unchecked")
    public <E> List<E> query(String namedQuery, Object... values) {
        return hibernateTemplate.findByNamedQuery(namedQuery, values);
    }
}

2. Create a service:

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class DefaultOrderService implements OrderService {
    @Autowired private HibernateGenericEntityManager entityManager;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Order order(Order order) {

        process(order);

        entityManager. save(order);

    }

    /** Transactional with class-level default propagation.

    private void process(Order order) {

    }

}

3. Create a spring context:

<beans>

    <context:component-scan base-package="persistence.hibernate"/>
    <context:component-scan base-package="service.order"/>
    <context:spring-configured/>

    <!-- Configure a datasource, sessionFactory, hibernateTemplate, HibernateTransactionManager, etc  -->

    <tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>

</beans>

4. Configure maven to weave in aspects at compile time:

             <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>1.6.0</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>1.6.0</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <complianceLevel>1.5</complianceLevel>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

My apologies for the long post. I have no time to write an article.

Jonathan Curran replied on Thu, 2008/11/06 - 1:12pm in response to: Mike Funk

Thanks for the example! I'll mess around with it when time permits.

jame jack replied on Mon, 2009/06/29 - 4:34pm

تحميل برامج برامج جوالات العاب بنات برامج تكنولوجيا كتب تعليم UltraSurf العاب برامج نت Internet Download Manager ProgDVB برامج مجانية أفضل المواقع العربية دليل مواقع مشاهدة محطات مشفرة Online TV Player 3.0.0.940 Internet Download Manager 5.17 Build 4 رقص شرقي anyTV Pro 4.32 OnLineLive 7.1.1 هزي يانواعم ProgDVB 6.06.2 SopCast 3.0.3 منتدى برامج نت Falco Image Studio 3.6 لعبة تزلج على الجليد UltraSurf 9.4 كاثرين هيغل Katherine Heigl محطة غنوة FreeZ Online TV 1.0 Free Video to Mp3 Converter 3.1.3.51 Advanced MP3 Converter 2.10 Xilisoft Video to Audio Converter 5.1.23.0515 Blaze Media Pro 8.02 AKRAM Media Creator 1.11 DVD Audio Extractor 4.5.4 Free WMA to MP3 Converter 1.16 لعبة نينجا المتقدم لعبة قذف كرة لعبة دراجات البهلوانية لعبة اعداء الغابة تحميل برامج Download DivX Subtitles 2.0 BullGuard 8.5 Google Chrome 2.0.181.1 Dev Dell Studio XPS Desktop 435T Intel Matrix Storage Manager A00 Gigabyte GA-EP45-UD3P Bios F9 Ambush HDConvertToX 1.1.229.1764 MSI Wind Nettop CS 120 Realtek Audio Driver 5.10.0.5618 Biostar T41-A7 6.x Realtek On-Board Audio Driver 5.10.0.5735 for 2000/2003/XP TweakNow RegCleaner 4.1.1 SpeedItup Free 4.97 برامج العاب - Internet Download Manager - برامج جوالات - العاب - محطة غنوة - قنوات فضائية - بنات - تكنولوجيا - كتب تعليم - UltraSurf - ق ذ -0

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.