MemeStorm

Exploring the Spring Framework and Application Development

Java Persistence API (JPA), Spring and Eclipse Web Tools Platform (WTP)

Posted in All by Jon on the October 30th, 2006

It’s time to add some persistence to our talks. I spent a good two hours trying to get Spring, JPA and Eclipse to play along. Here’s what I eventually did…So our goal is to create a project that I can run from within Eclipse, or deploy to something like Tomcat or an application server. It uses HSQLDB, though you can obviously change database, and Toplink Essentials (though you can obviously change JPA provider too). I use Tomcat 5.5.20 here. Oh, and Spring 2.0. All of the necessary software libraries (besides Tomcat) can be found bundled in the full Spring 2.0 distribution. I don’t use all of Spring’s JPA utilities either - I tried to stick to generic JPA stuff.

Our JPA Code

The only tricky part is setting up the application context for JPA’s entity manager factory. After that it’s plain sailing, writing nice JPA code. Here’s an example of one of the beans in our model:

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    String firstName;
    String lastName;

    @OneToOne
    @JoinColumn(name="pwd_id")
    Password password;

    @ManyToOne
    @JoinColumn(name="bldng_id")
    Building building;

    @OneToOne(mappedBy="owner")
    Cup cup;

    // omitted getters and setters
}

It’s a POJO, appropriately annotated. In this case we have some extra OneToOne (unidirectional), ManyToOne (unidirectional) and OneToOne(bidirectional) relationships, but feel free to omit them. This is pure POJO and JPA - there is no Spring in here at all.

That’s the kind of code we want to write for our domain model, so what about our DAO code? Here’s our full DAO:

@Transactional
public class MyDAOImpl implements MyDAO {

    private EntityManager em;

    // Spring will inject this:
    @PersistenceContext
    public void setEntityManager(EntityManager em) {
        this.em = em;
    }

    public Collection getUsers() {
        return em.createQuery("SELECT user from User user").
             getResultList();
    }

    public User loadUser(int id) {
        return em.find(User.class, id);
    }

    public void addUser(User user) {
        em.persist(user);
    }

    public Cup getCup(int id) {
        return em.find(Cup.class, id);
    }

}

This is pretty straightforward. The only Spring dependency we have here is the @Transactional, and that’s because I wanted Spring to make all the methods transactional and avoid writing blobs of repeated code. Notice the standard @PersistenceContext annotation. Spring will magically fill this in for us - it acts like a JPA container.

I like this code. It’s all neat, with minimal dependencies. Let’s look at how to wire it up to work with Spring.

Spring’s Application Context

I’ve created an applicationContext-jpa.xml configuration file for all the JPA stuff. It’s all pretty obvious once explained, I think…Here are all the bits with commentary:

First we set up a nice little property configurer, so you can just modify jdbc.properties to change the database:

<bean id="propertyConfigurer" class="org.....PropertyPlaceholderConfigurer">
    <property name="location" value="/WEB-INF/jdbc.properties"/>
</bean>

Now a simple datasource:

<bean id="dataSource"
   class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

Now for the meaty bit:

<bean id="entityManagerFactory"
   class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="MySpring"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="loadTimeWeaver">
    <bean
        class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
    </property>
    <!--  I'm not sure this is really necessary.. -->
    <property name="jpaVendorAdapter">
        <bean
          class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
            <property name="databasePlatform"
             value="oracle.toplink.essentials.platform.database.HSQLPlatform"/>
            <property name="generateDdl" value="true"/>
            <property name="showSql" value="true" />
        </bean>
    </property>
    </bean>

Now the important bit is the type of Spring entity manager factory you choose, and the weaver. Many JPA implementations (not all) require a runtime weaver of some kind. I had real trouble getting things to work with the SimpleLoadTimeWeaver in Eclipse. I suspect class loading errors were causing the problem. I ended up with the InstrumentationLoadTimeWeaver which requires that you start your Java VM with an additional argument:

-javaagent:/Java/workspace2/spring/dist/weavers/spring-agent.jar

To do this in Eclipse, hit “Run”, then “Run…” - select your server (for example, “Tomcat 5.5 Server”), hit the “Arguments” tab and insert the above in the “VM Arguments” box.

Some of the other weavers require me to modify Tomcat (by adding a context.xml file for example) to make Tomcat use Spring’s weaver - but I could not figure out how to do this with WTP - WTP provides no way for me to set this.

Moving on:

<!-- A simple transaction manager for our (single) EntityManagerFactory.  -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
    <property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven/>

Here we create a simple transaction manager, and tell Spring we want to use its declarative @Transaction management.

This makes Spring perform the magic @PersistenceContext/@PersitenceUnit injection:

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

Finally, we can declare our DAO:

<bean id="service" class="com.memestorm.service.jpa.MyDAOImpl" />

Note that we don’t specify the entity manager as a dependency. The bean post processor above will sort that out for us.

That’s it, we’re done! In the end, there wasn’t too much to it except for the wrangling with the various weavers and entity managers. Ben Hale provides a similar writeup though I got the same org.springframework.dao.InvalidDataAccessApiUsageException exceptions as some of his readers.

Download

The full source for the application is here. As usual, it assumes that you have the full Spring distribution unpacked in a sibling directory. Run the libraries Ant task to transfer the dependencies, and the server.sh in the db directory to start the database. I’ve run this within Eclipse (3.2.1) WTP (1.5.1) successfully, and deployed as a WAR to Tomcat 5.5.20.

springjpa.zip

Technorati Tags:
,


Print This Post Print This Post

Session-scoped Beans in Spring 2.0

Posted in All by Jon on the October 10th, 2006

Spring 2.0 introduces a new way of scoping beans. We’ve spoken about singleton scoped beans in the past and there are factory beans too. Now there are session, request and other types of bean scopes. As you might imagine, a Spring bean scoped to the sessions means that it lives as long as the session. This means that if you ask Spring’s IoC container for a bean that is session-scoped, it will instantiate it once only for that particular user’s session—different users in different sessions will get their own bean instances. It gets even cooler if you set this bean as a dependency for another bean that is a singleton. It still works, but in this case Spring injects a smart proxy to handle the dynamic bean swapping (the container bean will get a different dependent bean depending on the session). All of this magic is dead simple to implement and use.

How to do it

Let’s look at how to create a simple session-scoped bean that can be retrieved from the context. If you are using a DispatcherServlet (which you will be if you are using Spring’s MVC) then all you need to do is tag the bean as session-scoped in your application context configuration file. For example:

  <bean id="mybean" class="com.memestorm.ex.MyBean"
        scope=”session”/>

Not much to do…as you’ll see, the only difference is the session attribute. If you aren’t using the DispatcherServlet then you’ll need to add a (small) bit of extra configuration to web.xml:

  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>

You need to do this because of the mechanics of how this is implemented, which we’ll look at later. For now remember that if you’re already using Spring’s MVC, you don’t need to do anything. The bean, MyBean is nothing special—here’s the one we use:

    public class MyBean {
    	public MyBean() {
    		System.err.println("In Constructor!!!");
    	}
    }

So now that we’ve defined our bean in our context, how do we use it? Well, just like you’d use any other bean really! Here’s an example of a controller grabbing the bean from our application context:

 // retrieve context
 ApplicationContext ac = org.springframework.web.context.support.
   WebApplicationContextUtils.getRequiredWebApplicationContext(
                       request.getSession().getServletContext());
 // grab bean
 MyBean mb = (MyBean) ac.getBean("mybean");

This is what you’d do anyway. The key isn’t that you have change the way you program - but it’s the way Spring manages the creation of the bean.

What happens?

The bean (MyBean) won’t be created only once (a singleton) for all users—rather it will be created once for each user session. The magic is that it’s effectively tied to the user’s session (and created lazily as a result). Here’s a concrete use case used in the Spring documentation: User Preferences. If your user is logged on and you retrieve a session-scoped bean for the first time, it will be created. While the user is logged on (he has a session) that bean will remain effectively tied to the session so that if you access the bean again (from the context), it will simply retrieve it and not create it again.

You can test this with the supplied example. The index handler just tells me if the session is new (if it is, and you access the bean, you should expect a new instance to be created). The access handler actually tries to retrieve the bean from the context. You’d expect this to create the bean if the session is new, or simply just retrieve it if it’s not. The invalidate handler invalidates the session. Download the example and play - check the console to see the constructor message and when it appears.

More Advanced Work

Let’s look at the situation with dependencies. For example, imagine our session-scoped bean has a dependency on some singleton:

  <bean id="myotherbean" class="com.memestorm.ex.MyOtherBean" />

  <bean id="mybean" class="com.memestorm.ex.MyBean" scope="session">
    <property name="mob" ref="myotherbean" />
  </bean>

What happens now? Well, myotherbean will be created once with the context, and the same instance will be injected into each mybean instance that is created as each user creates a session. Neat huh? But I guess you’d expect that behaviour.

Even More Advanced Work

Let’s flip the injection described in the previous scenario. Imagine you have a bean that has a session-scoped bean as a dependency:

  <bean id="mybean" class="com.memestorm.ex.MyBean" scope="session">
	<property name="mob" ref="myotherbean" />
 	 <aop:scoped-proxy/>
  </bean>
  <bean id=”yetanotherbean” class=”com.memestorm.ex.YetAnotherBean”>
     <property name=”mybean” ref=”mybean” />
  </bean>

You’ll notice I had to do one surprising thing—it’s that magic AOP proxy incantation. Essentially the problem is this: if mybean is only created when accessed from a session, and multiple times for each different session, how do we know what to inject into yetanotherbean because yetanotherbean is a simple singleton created when the Spring context is created?

The answer is of course: it doesn’t and cannot know. So what we have to do is stuff in a proxy that behaves like the object (in fact it goes and grabs the object from the user’s session when you access it). Spring does all the heavy lifting for you in this case - all you need to do is add the scoped-proxy tag. This is pretty neat magic. I’ve included a download to a more advanced application that uses this approach too. Note that to do this proxying Spring needs cglib in the classpath.

Downloads


Print This Post Print This Post