Javelin: the JDJ 'World Class Award' winning, leader in visual, model driven Java development since 1996!

Javelin Evaluation
try it FREE for 15 days and realize the benefits and efficiencies of managing a POJO based domain model via live class diagrams instead of a plethura of text files.
Read more>>
expose your POJOs!

News:
Version 2.0.1 just released!

Home

Features and Benefits

Exposed Model Pattern: Why the buzz?

Framework overview

Getting Started

Licensing

Download<200kb)

API Reference

Community forum/blog

Download Javelin Modeler to view class diagrams

getting started

This tutorial will guide you through the simple steps required to integrate exPOJO into any Java web application. You may like to familiarize yourself with the key framework classes described in the framework overview

1. Set up Dependency Injection and Open Session/PersistenceManager in View

Your POJO model objects and your user interface objects will often need the facilities offered by the Service and Repository objects that are attached to the ModelExposer but you don't want to have to manually establish a reference from each of these objects directly to the ModelExposer and a singleton pattern won't work in a multithreaded environment like J2EE. That's where dependency injection comes in and it's really easy with exPOJO. In your web.xml file you simply add the following lines before any listener or servlet configurations:

<filter>
	<filter-name>exPOJO Filter</filter-name>
	<filter-class>com.sas.framework.expojo.servlet.ExpojoServletFilter</filter-class>
</filter>

<filter-mapping>
	<filter-name>exPOJO Filter</filter-name>
	<!-- CHANGE THIS TO THE NAME OF YOUR SERVLET CLASS -->
	<servlet-name>MyWebAppServlet</servlet-name>
</filter-mapping>
<!-- Listeners must appear after filters and before servlets -->
<listener>
        <!-- This will be notified of web application initiation and destruction -->
	<!-- CHANGE THIS TO THE NAME OF YOUR SERVLET LISTENER CLASS -->
        <listener-class>com.acme.myapp.context.MyAppServletContextListener</listener-class>
</listener>
MyWebAppServlet is the name of the servlet class of your web application. This is not an exPOJO dependent class. It might be an Echo2 servlet, a Wicket servlet, a Tapestry servlet or any other UI framework servlet. If your web application has multiple servlets you simply repeat the filter-mapping element for each servlet.

MyAppServletContext is a simple class that you create in your web application. More on this in step 4.

This is all that is required to configure the automatic dependency injection mechanism and Open Session/Persistence Manager in View. At any time during the servicing of a HTTP request your code needs access to a service or repository it can gain that access quickly and conveniently via the static method ModelObject.get() which returns the ModelObject associated with the current session.

As well as establishing the appropriate ModelObject instance for each session the exPOJO servlet filter also opens a transaction prior to servicing the HTTP request and commits it or rolls back (on error) after the HTTP request has been processed. This automatically implements the popular Open Session In View (HIbernate) or Open PersistenceManager in View (JDO) strategy. The HTTP request is processed in the context of an open transaction so navigation along relationships in your model and the subsequent on demand, transparent loading of objects into memory occurs without a "no current transaction" exception being thrown by your persistence engine.

2. Define a Repository Component

In a small project you will only need one Repository class. Put all methods that perform queries on the data store in there. eg., findUserByName, findOrganizationById etc., Create your Repository class by deriving from RepositoryComponent. It is good practice to create an intermediate abstract class that dictates the interface of your repository and from which you derive your concrete implementation classes. Repositories and services are retrieved from the ModelExposer by name so add a static name attribute for easy access and add a getName method that returns that name.

public class MyRepository extends RepositoryComponent
{
	public static final String name = "MyRepository";
	public String getName() { return name; }
	// Repository methods
	public abstract User findUserByName(String username);
	public abstract Collection findOrgsInCountry(String countryName);
}
public class MyRepositoryHibernate extends MyRepository
{
	public User findUserByName(String username)
	{
		// Hibernate query code goes here
		......
	}
	public Collection findOrgsInCountry(String countryName)
	{
		// Hibernate query code goes here
		......
	}
}

3. Define a Service Component

The service component is typically where your UI elements will invoke changes to the model. Services are established along the same lines as Repositories though you don't need a separate service class specific to persistence engine you want to use. The rule of thumb is that service methods change the model in some way by adding, removing or changing objects.

Derive an abstract Service class from ServiceComponent and then derive your concrete implementation from that class. Create a service getName method just like in the repository class.

public class MyService extends ServiceComponent
{
	public static final String name = "MyService";
	public String getName() { return name; }
	// Service methods
	public User createNewUser(String username, String password);
	public Employee createEmployee(Company company, Person person);
}

4. Putting it altogether: ExpojoServletContextListener

Define a class in your application that extends ExpojoServletContextListener. In step 1 we referred to this as MyAppServletContext (but you can call it whatever you want) and we set up web.xml so that this class is instantiated and notified whenever the web application is started or stopped.

Defining this is simple. It needs no constructor, just implementations of two methods declared abstract in the ExpojoServletContextListener class: addComponents and createPersistenceProviderFactory.
[You can optionally override initApplication() and destroyApplication() to perform any application specific initialization and clean up functions if your application needs that.]

addComponents is called whenever a ModelExposer is created for a new session. We use it to attach the repository and service components, defined in the previous steps, to the ModelExposer object.

createPersistenceProviderFactory is called once on web application startup to instantiate a persistence provider factory appropriate to the type of persistence engine we are using.

Here's the full source code of MyAppServletContext:
Note: this example is specific to Hibernate. If using the JPOX persistence engine simply comment out the Hibernate lines and uncomment the JPOX lines

package com.acme.myapp.context;

import java.lang.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;

import com.sas.framework.expojo.servlet.ExpojoServletContextListener;
import com.sas.framework.expojo.ModelExposer;
import com.sas.framework.expojo.PersistenceProviderFactory;

// Uncomment the line appropriate to your persistence engine
//import com.sas.framework.expojo.jdo.jpox.*;
import com.sas.framework.expojo.hibernate.*;

/**
 * Context for the My App web app.
 *
 * @author Chris Colman
 */
public
class MyAppServerContextListener extends ExpojoServletContextListener
{
    /**
     * Adds service and repository components to the ModelExposer.
     */
    public void addComponents(ModelExposer modelExposer)
    {
        modelExposer.addService(new MyService());

        // Uncomment the line appropriate to your persistence engine
        modelExposer.addRepository(new MyRepositoryHibernate());
        //modelExposer.addRepository(new MyRepositoryJpoxJdo());
    }

    /**
     * Create the persistence provider factoryDescribe here
     */
    public PersistenceProviderFactory
        createPersistenceProviderFactory(ServletContextEvent event)
    {
        // Uncomment the line appropriate to your persistence engine
        return new HibernatePersistenceProviderFactory();
        //return new JpoxJdoPersistenceProviderFactory();
    }
}

Example scenario: Adding a new user

Now that exPOJO has been integrated into your application you can access your exposed model as demonstrated in this scenario where a new user is about to be added to the database. The UI elements would gather user information such as username and password then call the repository to see if the username already exists. If it doesn't exist then a new User object would be created and saved:

// Get the respository so that we can look up a username
// [Note: the repository used here is the generic one, not the persistence
// engine specific one so your application code remains persistence engine
// agnostic, allowing you to easily try your app on a number of different
// persistence engines]
MyRepository myRepository = 
	(MyRepository)ModelExposer.get().getRepository("MyRepository");
if ( myRepository.findUserByName(username) != null )
{
    displayMessage("Username is already taken. Please enter a different username");
}
else
{
    // Get the service so that we can add a new user
    MyService myService =
	(MyService)ModelExposer.get().getService("MyService");
    User user = myService.createNewUser(username, password);
    if ( user != null )
    {
        displayMessage("A new user account has been added to the system");
    }
}

Advanced

This section is for more advanced use of exPOJO and is not necessary for most applications.

Using Javelin you can conveniently set up a service proxy that wraps calls to the real service object between begin, commit and rollback transaction calls - all with retry to handle optimistic locking clashes. See http://stepaheadsoftware.com/products/javelin/javelinfundamentals.htm for more details.

Nested Service/Transaction Calls

You will often find that a service method invokes another service method to perform it's task. This can be a direct call or it can be an indirect call via another service, a model object or possibly (rarely) a repository. The calls can be nested to any depth. As access to the service is usually via a  service proxy that is responsible for wrapping the call in a beginTx/commitTx/rollbackTx then it is possible to end up beginning a transaction has already begun or committing a transaction prematurely before the nested calls have completely returned.

exPOJO helps out here by permitting nesting of calls to PersistenceProvider.beginTx and PersistenceProvider.commitTx to any depth and keeping track of the nesting depth. It will only perform a true beginTX when at level zero and only perform a true commitTx when at level 1. Any calls to these methods above these depth levels will simply adjust the depth appropriately and return.

You can turn on tracing of the depth of the transaction call nesting using ModelExposer.get().setTraceTxDepth(true).


home | Javelin Home | Visual Classworks Home

Custom software development services

Copyright 1996, 2007 Step Ahead Software Pty Ltd. All rights reserved.
Java™ and Java™-based marks are trademarks or registered trademarks of Sun Microsystems.
Flash™ is a trade mark of Macromedia Inc.