Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

The PathProxy pattern: Persisting complex associations

Illustrated With JPA, Spring, and JSF

  • Print
  • Feedback

Page 2 of 7

Using the PathProxy pattern

The PathProxy class adds a supportive structure to your data model, as shown in in Figure 3.

Note that I'll be using the project-->manager-->developer table to introduce the PathProxy pattern. You probably wouldn't need the PathProxy class to handle those simple relationships; you could store them in lookup tables. The point is to keep things simple enough that you can focus on the PathProxy pattern. At the end of the article, we'll briefly discuss the steps required to add a task relationship to the table. Doing so is straightforward with the PathProxy in place.

Pathing, or lateral association

Although the PathProxy class has a parent, and I've used the term hierarchical, the PathProxy pattern doesn't necessarily refer to hierarchical information. Pathing is a better word for it. For example, tracking which QA engineer was working with which developer would be a "lateral" association.

Our sample application is built with Spring, JPA/Hibernate, and JSF. I've used Maven 2 as my build utility and tested the application on Tomcat 6. Installing and running the app is very easy: just unzip it, and type "mvn clean install" at the root (you'll need to have Maven 2 installed). You can also copy the tutorial.war file into Tomcat's /webapps directory. Finally, you can use mvn eclipse:eclipse to generate the appropriate .project files for Eclipse, and then just import the projects into your IDE. Maven includes similar goals for the other IDEs.

I've used JPA annotations to describe the persistence of the domain objects. I'll quickly walk you through the annotations and the Spring-JSF application setup. Then we can move on to learning about where the PathProxy class comes in.

The applicationContext.xml file in WEB-INF refers to one of two database configuration files:

Listing 1. Database configuration files in applicationContext.xml

<!--   <import resource="oracleConfig.xml" /> -->
   <import resource="hsqlConfig.xml" />

If you want to use Oracle, you can expose the oracleConfig and comment out the HSQLDB config. The app should work out of the box without any intervention from you, although the data will only be "persisted" to RAM. If you check out the oracleConfig.xml file, you'll see its set up to use Oracle XE running on localhost. It should be pretty easy to set that up for your environment if you want to.

In both database config files, the entityManagerFactory bean has <property name="generateDdl" value="true"/>, which means that the app will check for required database structures to realize the persistence mappings. If not found, it will automatically create them. Aside from being cool, this feature is great for rapid prototyping.

We'll rely closely on the sample application to see what's going on, so be sure you have it set up properly. Assuming that's done, let's get started!

PathProxy models project, manager and developer relationships.

Figure 3. PathProxy models project, manager and developer relationships

The domain model

We know we'll need three objects: Project, Manager, and Developer.

You'll see the classes in the example are marked up with annotations to define how they are persisted to the database. Take a look at the Manager property of Project.

We're not going to use PathProxy to model the Project-->Manager relationship because it doesn't need it. We'll use a simple many-to-many mapping instead. As you'll see, you can do that and still use PathProxy to track the relationship. This would be considered a kind of de-normalization of the database, because the information regarding Project-->Manager is repeated. To be clear, what we are doing is using a normal many-to-many for the Project-->Manager relationship, and then using PathProxy to represent that relationship when necessary -- specifically, when there is a developer on a given path.

We'll use the JPA many-to-many annotation to map the Project-->Manager relationship. We won't need a class for this, but JPA will create the Project_Manager table. Just keep in mind that the Project_Manager table is the cross-reference for the Project and Manager tables, not a table holding data about your ever-cheerful project manager.

The rest of the domain model is standard fare. You'll notice that the business objects implement the ManagedObject interface. ManagedObject allows us to treat all the objects the same in one important regard: we can be assured their ID is found under the getId() method. We also use the JPA's @MappedSuperclass annotation in the Person class. This is gives us the ability to keep the common functionality in the class while persisting the data to each subclass table. (See the Resources section for a nice discussion of JPA inheritance.)

Now let's take a closer look at the PathProxy class in your IDE. It has an entityType and entityId fields, which allow it to refer to any object in the system. One thing to notice about this mapping is the cascade flag on the children. What that means is that when you remove a PathProxy instance, the JPA provider (Hibernate in our case) will automatically remove any children associated with that instance. That's very important because you don't want any dangling PathProxy instances corrupting your data.

  • Print
  • Feedback

Resources
  • Download the sample application for this article, built with Spring, JPA/Hibernate, and JSF. The application build tool was Maven 2 and it was tested on Tomcat 6.
  • PathProxy isn't Matt Tyson's first published design pattern. Learn about his design strategies for Ajax-style development in JavaServer Faces: the AjaxCommand strategy and the AjaxComponent strategy, both published by JavaWorld.
  • The Spring Framework Documentation Section 3.3.4.1 explains Spring's lookup method injection.
  • See the JPOX homepage for a good discussion of JPA inheritance.
  • "Understanding the Java Persistence API" (Aditi Das, JavaWorld, January 2008) is a two-part introduction to Java-platform persistence with JPA. Part 2 walks through an example implementation of JPA annotations.
  • "J2EE design decisions" (Chris Richardson, JavaWorld, January 2006) explores five design patterns for implementing enterprise applications using lightweight frameworks such as Spring and Hibernate. An excerp from POJOs in Action; Manning Publications, January 2006.
  • "Get started with Hibernate" (Christian Bauer and Gavin King, JavaWorld, October 2004) is a short introduction to Hibernate written by its creator, Gavin King. Excerpted from Hibernate in Action; Manning 2004.)
  • Visit the JavaWorld Java Standard Edition research center for more articles about core Java programming tools, design patterns, and concepts.
  • Also see Network World's IT Buyer's Guides: Side-by-side comparison of hundreds of products in over 70 categories.