Search This Blog

Friday, October 5, 2012

JAX-RS 2.0 - Jersey 2.0 Preview - An Example

Introduction


JAX-RS 2.0 spec has reached public review status. Implementors of the API have been hard at work. One among them is Jersey. I have a vested interest in Jersey as I use it at work and therefore wanted to keep up to date on the changes in JAX-RS 2.0 and Jersey 2.0 and thus this BLOG. Jersey 2.0 is not backward compatible with Jersey 1.0 per their site and is instead a major re-write to correctly handle the new specification. When working with a previous REST provider, I found that when they created a 2.0 version of their product, they did not care to be backward "sensitive". I did not say compatible but sensitive :-). Backward sensitivity IMHO is a way to provide new functionality and refactor of an existing API in a way that provides a gradual migration path of consumers of the API and not requiring an all or nothing upgrade.

When backward incompatible changes are made to API's without changing package names, then binary incompatibilities surface when both versions of the API are required within the same class loader system. These incompatibilities can be easily absorbed by small scale adopters who can easily ensure all dependencies are upgraded simultaneously and only the latest version of the API is present. This requirement of simultaneous upgrade is however an arduous challenge for larger and more complex deployments whose development and deployment windows are very separated. Sure that one can look at OSGI or write their own class loaders if they should choose to but I am too dull headed for such extravagance.

In short what I want to ensure with Jersey 2.0 is the following use case:

There are three Services (REST services running within a Servlet container) written in Jersey 1.X. Each of the Services have multiple consumers but we are currently interested in the following where Service A calls Service B and Service C using their respective clients. A Service client is nothing more than a friendly API/library wrapping Jersey Client calls that can be distributed to different consumers of the service.

For the sake of discussion, let us consider that Service B is upgraded to Jersey 2.0 but Service C is not. As part of the upgrade, the maintainers of Service B provide a client to consume the service which is written in Jersey 2.0 as well. Will the Service clients of Service B and Service C be able to co-exist and function in Service A? Does the fact that Service A has not been upgraded to Jersey 2.0 cause problems for the clients of Service B and Service C to function in the container? In addition, let us say that Service A also gets upgraded to Jersey 2.0, then will the Service client for C that is using Jersey 1.X be able to function within Service A? Clearly, one option is to provide multiple clients of the service, one for Jersey 1.X and a second for Jersey 2.0. The same is achievable but does involve additional work of development and maintainence. So the question remains, whether the compatibility discussed will hold true or not? The BLOG and example provided herewith will evaluate the same.

JAX-RS 2.0 and what to expect


Client API

With earlier versions of the JAX-RS, the specification only accounted for a Server Side API for RESTful calls. The same led to different implementors of the Server API such as Jersey and RESTEasy independently developing a client side API (See my BLOG post on REST Clients). JAX-RS 2.0 will contain a Client API to support the server side specification. The JAX-RS 2.0 Client API is a major incorporation of the Jersey 1.X client API.

Asynchronous Support on Client and Server side

Client Side asynchronous support will allow a request to be dispatched in a non-blocking manner with results made available asynchronously. On the server side, long running requests that are I/O bound can be dispatched away, thus releasing the Application server thread to service other requests.

Validation

The lack of validation of data received from Headers, Body etc is something that I whined about in a previous BLOG. JAX-RS 2.0 will provide support for validation of request data.

Filters and Handlers

JAX-RS 2.0 specification accounts for Client and Server Filters. As in the case of the Client API, where implementer's provided their own versions of these filters for the Client and Server. The JAX-RS 2.0 specification absorbs the same into its API. For a more detailed understanding of changes in JAX-RS 2.0, a read of Arun Gupta's blog is recommended. This BLOG will be leaning on the Notes Web Service example that I had previously utilized where Notes can be created, updated and deleted via a client.

Jersey 2.0 and HK2



In previous version of my examples, I have used either Spring or Guice for injecting dependencies into Resources. At the time of this BLOG, I could not find the Spring or Guice support and have therefore used what Jersey 2.0 natively uses for its dependency injection and service location needs, i.e., HK2. HK2 is based on JSR 330 standard annotations. In the following example, a service binder utilizes HK2 and binds interface contracts to implementors as shown below. This binder which is defined in a "service" maven module is then used in the web maven module to enable injection of the NotesService:
public class ServiceBinder implements Binder {
  @Override
  public void bind(DynamicConfiguration config) {
    config.bind(BuilderHelper.link(NotesServiceImpl.class).to(NotesService.class).build());
  }
}

/**
 * Application class
 */
public class NotesApplication extends ResourceConfig {
  
  public NotesApplication() {
    super(NotesResource.class..);
    
    // Register different Binders
    addBinders(new ServiceBinder(), new JacksonBinder());
  }
}

/**
 * A Resource class injected with the Notes Service
 */
@Path("/notes")
public class NotesResource {
  @javax.inject.Inject
  private NotesService service; // Notes Service injection
  ...
}



Client



As previously mentioned, JAX-RS 2.0 supports a client API and Jersey provides an implementation of the same. At the time of writing this BLOG, I could not find hookins for Apache HTTP Client and therefore will be using the standard HttpClient for HTTP calls.

Client Creation

The process of configuring a client and creating the same is very similar to Jersey 1.X.
// Configuration for the Client
ClientConfig config = new ClientConfig();

// Add Providers
config.register(new JacksonJaxbJsonProvider());
config.register(new LoggingFilter());

// Instantiate the Client using the Client Factory
Client  webServiceClient = ClientFactory.newClient(config);

Executing REST Request

With Jersey 1.X, a typical POST to create a Note would have looked like-
NoteResult result = client.resource(UriBuilder.fromUri(baseUri).path("/notes").build())
        .accept(MediaType.APPLICATION_XML).entity(note,  MediaType.APPLICATION_XML).post(NoteResult.class);
The same request using the JAX-RS 2.0 client looks like:
NotesResult result = client.target(UriBuilder.fromUri(baseUri).path("/notes").build())
        .request(MediaType.APPLICATION_XML) // Request instead of accept
        .post(Entity.entity(note, MediaType.APPLICATION_XML_TYPE), NoteResult.class);
The primary difference seems to be where the Resource is identified as "target" rather than "resource". There is no "accepts" method but is replaced with "request" for media type. The Entity is built from a Entity Builder method which returns an instance of java.ws.rs.client.Entity. Overall the API seems quite flowing and does not seem to conflict with the Jersey 1.X client API.

Server Changes



One of the changes I wanted to work with is the Validation but I do not believe the same has been fully implemented as yet. Apart from the Async support mentioned earlier, one area of interest for me  is the Filters and Name Binding feature of JAX-RS.

Name binding and Filter

For those who have used Jersey's ContainerRequest and ContainerResponse Filters, the JAX-RS 2.0 equivalents should be quite familiar. An example of a simple ContainerRequestFilter that logs header attributes is shown below:
@Provider
@Loggable
public class LoggingFilter implements ContainerRequestFilter {
  private static final Logger LOG = Logger.getLogger(LoggingFilter.class);

  @Override
  public void filter(ContainerRequestContext requestContext) throws IOException {
    MultivaluedMap<String, String> map = requestContext.getHeaders();
    LOG.info(map);
  }
}
The annotation @Loggable shown above is a custom one that I created to demonstrate the Name Binding features of JAX-RS 2.0 where a Filter or Handler can be associated with a Resource class, method or an invocation on the client. In short this means one has finer grained control over which methods/resources the filter or handler is made available to. The annotation @Loggable is shown below:
@NameBinding
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Loggable {
}
With the above, if we wish to apply the LoggingFilter only to a specific method of a Resource, one simply has to annotate the method with @Loggable:
@Path("/notes")
public class NotesResource {
  @POST
  @Loggable // Will be logged
  public Response create(Note note) {
   ...
  }

  @GET // No annotation @Loggable added
  public Note get(Long noteId) {
    ...
  }
If one wanted to apply the filter on a global level, then Global Binding is used where annotating the filter or handler with @GlobalBinding makes it applicable to all resources of an application.

Asynchronous HTTP



This is where its time for fun, at least for me :-). With Servlet 3.0, one can utilize NIO features and thus free service threads from blocking IO Tasks. Jersey supports suspending the incoming connection and resuming it at a later time. On the client side, the ability to dispatch requests asynchronously is a convenience.

Fictitious Requirements of the Notes Service
  • Notes Client should be able to submit a large number of Notes for creation. The Service should not block the JVM Server thread while it waits to submit but instead should background the same. Client should be notified of a Task ID asynchronously when it becomes available.
  • Notes Client should be able to obtain the status of Note creation asynchronously. The Service should not block the JVM Server thread while waiting for task completion. Upon obtaining the task result, the client should be notified of the same.
  • Notes Client should be able to register a listener that is notified of Note Creation events from the server

Posting a list of Notes for Creation

A list of Notes are submitted to the resource to asynchronously create them. The call itself is asynchronous with a Task ID being delivered to the InvocationCallback when available. One could accomplish the same via an Executor Service etc but this feature simplifies the operation.
 @Override
  public void submitAsync(List<Note> notes, InvocationCallback<Long> taskCallback) {
    webServiceClient.target(UriBuilder.fromUri(baseUri).path("/notes/async").build())
        .request(MediaType.TEXT_PLAIN).async()
        .post(Entity.entity(new NotesContainer(notes), MediaType.APPLICATION_XML), taskCallback);
  }
On the server side, the AsyncNotesResource handles the POST as shown below:
  @POST 
  public void createAsync(@Suspended final AsyncResponse response, final NotesContainer notes) {

    QUEUE_EXECUTOR.submit(new Runnable() {
      public void run() {
        try {
          // This task of submitting notes can take some time
          Long taskId = notesService.asyncCreate(notes.getNotes());
          LOG.info("Submitted Notes for Creation successfully, resuming client connection with TaskId:"
            + taskId);
          // Resume the connection
          response.resume(String.valueOf(taskId));
        }
        catch (InterruptedException e) {
          LOG.error("Waiting to submit notes creation interrupted", e);
          response.resume(e);
        }
      }
    });
  }
One can also obtain a java.util.concurrent.Future using the API if desired.

Obtaining Result of Task Processing Asynchronously

The InvocationCallback of the POST request will be provided a Task ID. Using this Task ID, an asynchronous GET request can be dispatched to obtain the results of the task. As the task might not be completed at the time of the request, the client issues the request in an asynchronous manner and is provided the results of the task when available through the InvocationCallback.
 public void getAsyncNoteCreationResult(Long taskId,
    InvocationCallback<NotesResultContainer> resultCallback) {
    webServiceClient.target(UriBuilder.fromUri(baseUri).path("/notes/async/" + taskId).build())
        .request(MediaType.APPLICATION_XML).async().get(resultCallback);
  }
The Server resource as shown below will not block the JVM server thread but will background the process of obtaining the Task results and the backgrounded process will resume the client connection with the task result when available. Also a time out is set on the request, if the server is not able to respond within the alloted period of time, then a 503 response code is sent back with a "Retry-After" header set to 60 sec.
@GET 
@Path("{taskId}") 
public void getTaskResult(@Suspended final AsyncResponse ar, @PathParam("taskId") final Long taskId) {

    LOG.info("Received Request to Obtain Task Result for Task:" + taskId);
    ar.setTimeout(10000L, TimeUnit.MILLISECONDS);
    ar.setTimeoutHandler(new TimeoutHandler() {
      
      @Override 
      public void handleTimeout(AsyncResponse asyncResponse) {   
        // Respond with 503 with Retry-After header set to 60 seconds
        // when the service could become available.     
        asyncResponse.cancel(60);
      }
    });
    QUEUE_EXECUTOR.submit(new Runnable() {

      @Override public void run() {
        try {
          // This call will block until results are available.
          List<Long> noteIds = notesService.getAysyncNoteCreationResult(taskId);

          NotesResultContainer resultContainer = new NotesResultContainer();
          ....
          LOG.info("Received Note Creation Result, resuming client connection");
          ar.resume(resultContainer);
        }
        catch (InterruptedException ex) {
          LOG.info("Interrupted Cancelling Request", ex);
          ar.cancel();
        }
      }
    });
  }
Server Sent Events

A Feature of Jersey, though I believe not to be really a feature of JAX-RS is the ability to listen to Server sent events. The same is accomplished by the client obtaining an instance of org.glassfish.jersey.media.sse.EventChannel from the Service which then receives events published by the server. The channel is kept alive until disconnected. The Client code to obtain the EventProcessor is shown below:
   WebTarget target = webServiceClient.target(UriBuilder.fromUri(baseUri)
            .path("/notes/async/serverSent").build());
   
   // Register a reader for the Event Processor
   target.configuration().register(EventProcessorReader.class);

   // Obtain an event Processor from the Service
   EventProcessor processor = target.request().get(EventProcessor.class);

   processor.process(new EventListener() {
     public void onEvent(InboundEvent inboundEvent) {
       Note inboundNote = inboundEvent.getData(Note.class);

       for (NoteListener listener : serverEventListeners) {
         listener.notify(inboundNote);
       }
      }
   });
On the service end, a thread is started that will dispatch Note creation events to the channel.
  @Produces(EventChannel.SERVER_SENT_EVENTS)
  @Path("serverSent")
  @GET
  public EventChannel serverEvents() {
    final EventChannel channel = new EventChannel();
    new EventChannelThread(channel, notesService).start();

    return seq;
  }
  
  public class EventChannelThread extends Thread {
     ...
     public void run() {
        // While loop jargon ommited for lack of real estate
        channel.write(new OutboundEvent.Builder().name("domain-progress")
                  .mediaType(MediaType.APPLICATION_XML_TYPE).data(Note.class, noteToDispatch).build());

     }
  }

Example Project



An example project can be downloaded from HERE.

As mentioned previously, the example uses the concept of CRUD as related to a Note. A multi-module maven project is provided herewith that demonstrates the Notes application as written with Jersey 1.X and Jersey 2.X. The Jersey 2.X version has some additional features such as ASYNC, Name Binding and Filter that are demonstrated. In addition, there is a compatibility-test project that evaluates the compatibility concerns that I had mentioned at the beginning of my BLOG. Please note that 2.0-SNAPSHOT of Jersey is being used. A brief description of the maven modules you will find in the example:
  • Notes-common: Contains Data transfer objects and common code used by the Jersey 1.X and Jersey 2.X applications
  • Notes-service: Contains Java classes that are functional services for managing the Notes.
  • Notes-jersey-1.X: Contains Client, Webapp and Integration test modules that demonstrate Jersey 1.X.
  • Notes-jersey-2.X: Contains Client, Webapp and Integration test modules that demonstrate Jersey 2.X features
In order to exercise the compatibility tests two test webapps are created, one using Jersey 1.X and the second using Jersey 2.0. The Notes-client's of Jersey 1.X and Jersey 2.X are exercised within both mentioned test webapps to check for compatibility problems.
The compatibility integration test invokes a resource "/compatibility" on a test web app that is developed using jersey. When the resource is invoked, both the Notes Jersey Clients are exercised to perform CRUD operations using RESTful calls to a Notes Web service Webapp. There are two versions of the test-jersey-webapp, one written in Jersey-1.X and the second in Jersey 2.0.

You can run the full suite of Integration tests merely by executing a "mvn install" from the root level of the project. If you wish to run individual tests, you can also drill down into the Notes-jersey-1.X and Notes-jersey-2.0 modules and execute the same command.

Compatibility Test Results



So can Jersey 2.0 and Jersey 1.X co-exist in the same class loader system? The answer seems to be "Yes" but with some effort. jersey-client-1.X.jar depends on jersey-core-1.X.jar. The latter bundles JAX-RS 1.X (javax.ws.rs.*) packages in it. jersey-client-2.X depends on javax.ws.rs.* packages that are part of JAX-RS 2.0 and therefore requires that JAX-RS API 2.0 is available.

If an application that is running Jersey 1.X wishes to utilize a Jersey 1.X and Jersey 2.X client to call other web services, it is best to upgrade the service in question. The reasoning for the same is best established by the following use case:

Consider the javax.ws.rs.core.UriBuilder from jersey-core-1.X.jar:

public abstract class UriBuilder {
 public abstract UriBuilder uri(URI uri) throws IllegalArgumentException;
}

An implementation by Jersey of the same is com.sun.jersey.api.uri.UriBuilderImpl which is as included part of jersey-core-1.X.jar.

Now the JAX-RS 2.0 version of UriBuilder has additional abstract methods one of which is shown below:

public abstract class UriBuilder {
 public abstract UriBuilder uri(URI uri) throws IllegalArgumentException;

 // New Method Added as part of JAX-RS 2.0
 public abstract UriBuilder uri(String uri) throws IllegalArgumentException;
}
An implementation of the same is org.glassfish.jersey.uri.internal.JerseyUriBuilder.

When a UriBuilder is loaded, it is important that the implementation that defines all the abstract methods of UriBuilder is loaded. If not, one would get see an exception like:
java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder;
The same problem could exist for other JAX-RS 2.0 classes for which Jersey 1.X does not have concrete implementations. As the JAX-RS 2.0 API has to exist in the classpath, one needs to ensure that JAX-RS 1.X API classes are not included as well.

The jersey-core-1.X.jar includes javax.ws.rs.* packages from jax-rs 1.0 API. Re-bundling the jersey-core-1.X jar without these packages and including jersey 2.0 and jax-rs 2.0 API classes will always ensure that the API's have the latest and complete implementations.

In addition, the implementation of javax.ws.rs.ext.RuntimeDelegate is responsible for instantiating a version of UriBuilder. If the Jersey 1.X version of RuntimeDelegate is chosen at runtime, then it will attempt to load com.sun.jersey.apu.uri.UriBuilderImpl which will not have the abstract methods defined as part or JAX-RS 2.0's UriBuilder. For this reason, the org.glassfish.jersey.server.internal.RuntimeDelegateImpl must be chosen so that the JAX-RS 2.0 implementation of UriBuilder, i.e., org.glassfish.jersey.uri.internal.JerseyUriBuilder is always created. The same is accomplished by defining in META-INF/services a file java.ws.rs.ext.RuntimeDelegate that contains a single line, org.glassfish.jersey.uri.internal.JerseyUriBuilder.

The compatiblity-test web applications exercise the above mentioned route in addition to including a custom version of jersey-core-1.X.jar which is nothing more than a version that is stripped of javax.ws.rs.* java packages.

With the above changes, I found that my compatibility tests passed. Of course I am working under the assumption that the JAX-RS 2.0 API classes did not change method signatures in an incompatible way :-).

Conclusion



Overall I feel that the JAX-RS 2.0 implementation with the unification of the Client API is definitely a move in the right direction. Jersey 2.0-SNAPSHOT also seemed to work well from an API and implementation perspective. It is heartening to know that co-existence can be achieved using Jersey 1.X and Jersey 2.0.The Jersey folks have also stated that they will be providing a migration path for Jersey 1.X adopters which is really professional of them. Some work has already been done to that effect on their site.

On the Async features of JAX-RS 2.0, I see potential value on the server side with NIO. On the client side, I find the API to be a convenience. It is arguable that in a clustered stateless environment client side ASYNC might provide limited value.

I have not covered all JAX-RS 2.0 features but only those that have interested me. There are many changes and I might investigate the remaining come another day. Finally, if I have got some areas wrong or my understanding if flawed, I look forward to your corrections on the same.

UPDATE - An example of the released jersey 2/jax-rs 2.0 that uses Spring DI is now available

Sunday, July 8, 2012

Spring MVC 3.1 Presentation and Tutorial

A few months ago, I had a chance to present on Spring MVC. It was a simple 45 minute presentation but I had a blast doing it.  A friend of mine had asked whether I could share the same and this BLOG post is exactly that.

My audience for the presentation had no experience with the framework and therefore my presentation was geared toward introducing the same to them. A Spring MVC presentation without supporting code is like having a cake without the icing. So included herewith is also the code I developed for the same.

The model object of interest for the demo code is an Application in some company's domain. It could be any application such as a web app, web service or whatever. The Application has a single property, its name. The final example demonstrates connectivity between applications using arbor.js to display the relationship.

The examples provided are in the form of a multi-module maven project and are meant to gradually progress a reader into Spring MVC.

1. springMvcBasic

This is the basic project and provides the simplest example of a Controller that renders a list of applications.

 2. springMvcFormValidation

The springMvcFormValidation module demonstrates the use of JSR 303 validations of Forms and form submission.

3. springMvcRequestResponses

This project demonstrates the use of the REST support of Spring MVC by sending and receiving XML and JSON.

4. springMvcDecorated

The springMvcDecorated module is conglomeration of the above examples and also demonstrates the following:

a. Internationalization
b. Spring Theme support using Twitter Bootstrap for the styling.
c. arbor.js for demonstrating application interaction
d. displayTag and dataTables.js for table support
e. sitemesh for decorating pages

Enter into each project and execute a mvn jetty:run to start the application. You can access each application at the corresponding ports.

The presentation is attached herewith.  The code samples can be downloaded from here.

Follow the presentation along with the provided examples to see it in action. I am grateful to the multitude of community presentations and blogs that helped me with my presentation. 

Friday, June 29, 2012

Spring Data MongoDB Example

Sometime ago I had Blogged about using Morphia with Mongo DB. Since then I have come across the Spring Data project and wanted to take their API for Mongo  on a ride. So this BLOG is duplicating the functionality of what was present in the Morphia one with the difference that it uses Spring Data and demonstrates Mongo Map-Reduce as well. As most of my recent Blogs that use Spring, I am going to be using a pure JavaConfig approach to the example.

 1. Setting up Spring Mongo 


The Spring API provides an abstract Spring Java Config class, org.springframework.data.mongodb.config.AbstractMongoConfiguration. This class requires the following methods to be implemented, getDatabaseName() and mongo() which returns a Mongo instance. The class also has a method to create a MongoTemplate. Extending the mentioned class, the following is a Mongo Config:
@Configuration
@PropertySource("classpath:/mongo.properties")
public class MongoConfig extends AbstractMongoConfiguration {
 
  private Environment env;  
 
  @Autowired
  public void setEnvironment(Environment environment) {
    this.env = environment;
  }

  @Bean
  public Mongo mongo() throws UnknownHostException, MongoException {
    // create a new Mongo instance
    return new Mongo(env.getProperty("host"));
  }

  @Override
  public String getDatabaseName() {
    return env.getProperty("databaseName");
  }
}

2. Model Objects and Annotations 


As per my former example, we have four primary objects that comprise our domain. A Product in the system such as an XBOX, WII, PS3 etc. A Customer who purchases items by creating an Order. An Order has references to LineItem(s) which in turn have a quantity and a reference to a Product for that line.

2.1 The Order model object looks like the following:

// @Document to indicate the orders collection
@Document(collection = "orders")
public class Order {
  // Identifier
  @Id
  private ObjectId id;

  // DB Reference to a Customer. This is a Link to a Customer from the Customer collection
  @DBRef
  private Customer customer;

  // Line items are part of the Order and do not exist independently of the order
  private List<LineItem> lines;
 ...
}
The identifier of a POJO can be ObjectId, String or BigInteger. Note that Orders is its own rightful mongo collection however, as LineItems do not exist without the context of an order, they are embedded. A Customer however might be associated with multiple orders and thus the @DBRef annotation is used to link to a Customer.

3. Implementing the DAO pattern 


One can use the Mongo Template directly or extend or compose a DAO class that provides standard CRUD operations. I have chosen the extension route for this example. The Spring Mongo API provides an interface org.springframework.data.repository.CrudRepository that defines methods as indicated by the name for CRUD operations. An extention to this interface is the org.springframework.data.repository.PagingAndSortingRepository which provides methods for paginated access to the data. One implementation of these interfaces is the SimpleMongoRepository which the DAO implementations in this example extend: 
// OrderDao interface exposing only certain operations via the API
public interface OrderDao {
  Order save(Order order);

  Order find(ObjectId orderId);

  List<Order> findOrdersByCustomer(Customer customer);

  List<Order> findOrdersWithProduct(Product product);
}

public class OrderDaoImpl extends SimpleMongoRepository<Order, ObjectId> implements OrderDao {

  public OrderDaoImpl(MongoRepositoryFactory factory, MongoTemplate template) {
    super(new MongoRepositoryFactory(template).<Order, ObjectId>getEntityInformation(Order.class), template);
  }

  @Override
  public List<Order> findOrdersByCustomer(Customer customer) {
    // Create a Query and execute the same
    Query query = Query.query(Criteria.where("customer").is(customer));

    // Note the equivalent of Hibernate where one would do getHibernateTemplate()...
    return getMongoOperations().find(query, Order.class);
  }

  @Override
  public List<Order> findOrdersWithProduct(Product product) {
   // Where the lines matches the provided product
    Query query = Query.query(Criteria.where("lines.product.$id").is(product));
    return getMongoOperations().find(query, Order.class);
  }
}
One of the quirks that I found is that I was not able to use Criteria.where("lines.product").is(product) but had to instead resort to using the $id. I believe this is a BUG and will be fixed. Another peculiarity I found between Mongo 1.0.2.RELEASE and the milestone of 1.1.0.M1 was in the save() method of SimpleMongoRepository:
//1.0.2.RELEASE
public <T> T save(T entity) {
}

// 1.1.0.M1
public <S extends T> S save(S entity) {
}
Although the above will not cause a Runtime error upon upgrading due to erasure, it will force a user to have to override the save() or similar methods during compile time. If upgrading from 1.0.2.RELEASE to 1.1.0.M1, you will have to add the following to the OrderDaoImpl in order for it to compile:
@Override  
@SuppressWarnings("unchecked")
public Order save(Order order) {
   return super.save(order);
}

4. Configuration for the DAO's


A Java Config is set up that wires up the DAO's
@Configuration
@Import(MongoConfig.class)
public class DaoConfig {
  @Autowired
  private MongoConfig mongoConfig;

  @Bean
  public MongoRepositoryFactory getMongoRepositoryFactory() {
    try {
      return new MongoRepositoryFactory(mongoConfig.mongoTemplate());
    }
    catch (Exception e) {
      throw new RuntimeException("error creating mongo repository factory", e);
    }
  }

  @Bean
  public OrderDao getOrderDao() {
    try {
      return new OrderDaoImpl(getMongoRepositoryFactory(), mongoConfig.mongoTemplate());
    }
    catch (Exception e) {
      throw new RuntimeException("error creating OrderDao", e);
    }
  }
  ...
}

5. Life Cycle Event Listening 


The Order object has the following two properties, createDate and lastUpdate date which are updated prior to persisting the object. To listen for life cycle events, an implemenation of the org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener can be provided that defines methods for life cycle listening. In the example provide we override the onBeforeConvert() method to set the create and lastUpdateDate properties.
public class OrderSaveListener extends AbstractMongoEventListener<Order> {
  /**
   * This method is responsible for any code before updating to the database object.
   */
  @Override
  public void onBeforeConvert(Order order) {
    order.setCreationDate(order.getCreationDate() == null ? new Date() : order.getCreationDate());
    order.setLastUpdateDate(order.getLastUpdateDate() == null ? order.getCreationDate() : new Date());
  }
}

6. Indexing 


The Spring Data API for Mongo has support for Indexing and ensuring the presence of indices as well. An index can be created using the MongoTemplate via:
mongoTemplate.ensureIndex(new Index().on("lastName",Order.ASCENDING), Customer.class);

7. JPA Cross Domain or Polyglot Persistence


If you wish to re-use your JPA objects to persist to Mongo, then take a look at the following article for further information about the same.
 http://www.littlelostmanuals.com/2011/10/example-cross-store-with-mongodb-and.html

8. Map Reduce


The MongoTemplate supports common map reduce operations. I am leaning on the basic example from the Spring Data site and enhancing it to work with the comments example I have used in all my M/R examples in the past. A collection is created for Comments and it contains data like:
{ "_id" : ObjectId("4e5ff893c0277826074ec533"), "commenterId" : "jamesbond", "comment":"James Bond lives in a cave", "country" : "INDIA"] }
{ "_id" : ObjectId("4e5ff893c0277826074ec535"), "commenterId" : "nemesis", "comment":"Bond uses Walther PPK", "country" : "RUSSIA"] }
{ "_id" : ObjectId("4e2ff893c0277826074ec534"), "commenterId" : "ninja", "comment":"Roger Rabit wanted to be on Geico", "country" : "RUSSIA"] }

The map reduce works of JSON files for the mapping and reducing functions. For the mapping function we have mapComments.js which only maps certain words:
function () {
   var searchingFor = new Array("james", "2012", "cave", "walther", "bond");
   var commentSplit = this.comment.split(" ");
 
    for (var i = 0; i < commentSplit.length; i++) {
      for (var j = 0; j < searchingFor.length; j++) {
        if (commentSplit[i].toLowerCase() == searchingFor[j]) {
          emit(commentSplit[i], 1);
        }
      }
    }
}
For the reduce operation, another javascript file reduce.js:
function (key, values) {
    var sum = 0;
    for (var i = 0; i < values.length; i++) {
        sum += values[i];
    }
    return sum;
}
The mapComment.js and the reduce.js are made available in the classpath and the M/R operation is invoked as shown below:
public List<ValueObject> mapReduce() {
    MapReduceResults<ValueObject> results =  getMongoOperations().mapReduce("comments", "classpath:mapComment.js" , "classpath:reduce.js", ValueObject.class);

    return Lists.<ValueObject>newArrayList(results);    
}
Upon executing the map reduce, one would see results like:
ValueObject [id=2012, value=119.0]
ValueObject [id=Bond, value=258.0]
ValueObject [id=James, value=241.0]
ValueObject [id=Walther, value=134.0]
ValueObject [id=bond, value=117.0]
ValueObject [id=cave, value=381.0]


Conclusion

As always, the Spring folks keep impressing me with their API. Even with the change to their API, they preserved binary backward compatibility thus making an upgrade easy. The MongoTemplate supports common M/R operations, sweet! I have not customized the M/R code to my liking but its only a demo after all.
I quite liked the API, it is intuitive and easy to learn. I clearly have not explored all the options but then I am not really using Mongo at work to do the same ;-)

Example


Download the example from here. It is a maven project that you can either import into Eclipse or simply run mvn test from the command line to see the simple unit tests in action. The tests themselves make use of an embedded mongo instance courtesy of https://github.com/michaelmosmann/embedmongo.flapdoodle.de.
Enjoy!

Sunday, February 19, 2012

Jersey JAX-RS MVC Killed the Spring MVC Star

JAX-RS is arguably the de-facto standard for creating RESTful web services in Java. Most JAX-RS providers have a way to implement a de-coupled MVC paradigm; much like Spring MVC. This BLOG will demonstrate how Jersey JAX-RS can be used as an MVC web framework and will spend some time discussing the difference between Jersey MVC and Spring MVC. As part of the investigation, the Flight Application that I have previously demonstrated using Spring MVC will be translated to use Jersey MVC.

Some of the additional goals of this BLOG are:
1. Integrate with Spring Security for authentication/authorization
2. Use Spring for the Dependency injection
3. Use Twitter Bootstrap for the view part

Front Controller:
Both Spring MVC and Jersey have an implementation of the Front Controller design pattern with the DispatcherServlet from Spring MVC and ServletContainer from Jersey. The former dispatches to Controller classes while the later dispatches to Resource classes.

Controller/Resource:
In a typical Spring MVC Controller we have a ModelAndView object returned with data for the view tier to digest:
@Controller
@Request("/airports.html")
public class AirportsController {
  @RequestMapping(method = RequestMethod.GET)
  public ModelAndView getAirports() {
    List<Airport> airports = airportService.getAirports();

    ModelAndView mav = new ModelAndView("/airports");
    mav.addObject("airports", airports);

    return mav;
  }
}
Jersey provides a class equivalent to ModelAndView called Viewable that defines the view to be used and also houses the model objects:
@Path("/airports.html")
public class AirportsResource {
  @GET
  public Viewable getAirports() {
    List<Airport> airports = airportService.getAirports();
    Map<String, List<Airports>> modelMap = Maps.newHashMap();
    modelMap.put("airports", airports);

    return new Viewable("/airports", modelMap);
  }
}
View Processing:
Spring MVC provides View Resolvers to resolve the template name to a template reference.
In the Jersey MVC land, implementations of the ViewProcessor interface are used to resolve a template name to a template reference. In addition, they are also responsible for processing the template and the results of which are written to the output stream. One such processor is available in the Jersey code base for JSP's, i.e., the JSPTemplateProcessor.  The processor requires the location of the JSP files and the same is made available via the argument of JSTTemplatesBasePath.  The Viewable interface lends itself to providing alternate View Processors for other templating languages like Free Marker and Velocity but the same would need to be built:
<filter>
  <filter-name>jersey</filter-name>
  <filter-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</filter-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
      <param-value>/WEB-INF/pages</param-value>
    </init-param>
</filter>
View:
In the JSP, all the model objects provided by the Resource tier are easily accessed by using a prefix of "it".  For example
${it.airports} as shown below:
<display:table name="${it.airports}" class="table table-condensed"
     requestURI="" id="a" export="true" pagesize="10">
   <display:column title="Code" property="code" sortable="true"/>
   <display:column title="Name" property="name" sortable="true" />
   <display:column title="City" property="city" sortable="true"/>
</display:table>
With the above, one has the exact same functionality between Spring MVC and Jersey. It is important to note that with Spring MVC however, there are a bunch of options for the return type by which the view is resolved. Spring MVC follows a convention based approach for its Controllers and return types can be quite a few:
  • ModelAndView object
  • Model object, for example, a List of Airports
  • Map of Model objects
  • A View object
  • A String that represents a View name
I will not get into details of the how the above are achieved by Spring MVC as it is beyond the scope of this BLOG. It is sufficient to accept that Spring MVC does support these alternate return types and follows a convention based approach to view resolution.

Accessing Request Data:
Web applications need to have access to request information like HTTP Headers, Cookies, Query Parameters and Form data (discussed later).  Both Spring MVC and Jersey JAX-RS have annotations that help extract the same.
@RequestMapping(method=GET)
public void foo(@RequestParam("q") String q, @CookieValue("c") String c, 
                @RequestHeader("h") String h) {
    // Spring MVC
}

@GET 
@Path
public void foo(@QueryParam("q") String q, @CookieParam("c") String c,
    @HeaderParam("h") String h) {
    // JAX-RS
}

Form Data Management:
Handling Form data and validating the same is one area where every MVC framework has to be tested against.

From a binding perspective, when a form is submitted, one would like to have the form details map to a POJO. With Spring MVC, a form POJO is automatically populated with the details of the HTML Form coupled with the ability of having the contents of the Form being validated and results made available via a BindingResult object as shown below:
public class FlightController {
  @RequestMapping(method=POST)
  public ModelAndView searchFlights(FlightSearchCriteria criteria, BindingResult result) {
     ...
     if (result.hasErrors()) { ... }
     ..
  }
}
In the JAX-RS domain, there are a few ways to access Form parameters:

1. Using the Form object or a MultiValuedMap and explicitly extracting the form data by name:
    public Viewable searchFlights(Form form) {
      String fromAirport = form.getFirst("from");
      String toAirport = form.getFirst("to");
      ...
    }
2. Using @FormParam annotation for auto injection of Form parameters:
public Viewable searchFlights(@FormParam("from") String fromAirport, @FormParam("to") String toAirport) {
   ...
}
3. Using @InjectParam with a Java POJO whose attributes are annotated with @FormParam:

Using @FormParam when there are  a few Form parameters works well but fails when there are multiple parameters as the same translates to a very long method signature. In such cases a single object can house the individual parameters as shown below with the Object being injected automatically to the controller method due to the magic of Jersey's Injectable annotation. Read more about the same from Valotas BLOG:
public class FlightSearchCriteria {
  @FormParam("from")
  String fromAirport;

  @FormParam("to")
  String toAirport;
  ...
}

public class FlightResource {
  public Viewable searchFlights(@InjectParam FlightSearchCriteria criteria) {
    ....
  }
}
With the above, Jersey's MVC is able to map a form object to a POJO but it does involve adding annotations of @FormParam for each form parameter. With the Spring MVC binding, one did not have to deal with the same. In addition, the above examples of Jersey MVC are missing validation of the Form. To achieve the same, one might be able to create a custom Injection Provider to validate and provide the validation results as part of the method signature. I did not find a ready way to do the automatic validation and thus leave that effort for the making of a future BLOG post. That said, validation can easily be performed using JSR 303 validation or a custom validator easily enough programatically within the Jersey MVC resource method:
public Viewable searchFlights(@InjectParam FlightSearchCriteria criteria) {
    ...
    Set<ConstraintViolation<FlightSearchCriteria>> violations = validator.validate(criteria);

    if (violations.size() > 0) {
      modelMap.put("errors", violations);

      return ...;
    }
    ...
}
On the view, displaying the errors on a global level is pretty easy using JAX-RS, as one can simply loop over the violations and display the violation message. Displaying an error message corresponding to each violation explicitly, well Spring MVC has tag support to do the same and although achievable by writing a custom tag, it is an added effort for a Jersey MVC application.

Http Session Variables:
If an application wishes to use the Http Session for managing state, Spring MVC has annotated convention based support for the same. Consider the following example from the petclinic app where managing the lifecycle of the pet in the HTTP session is shown:
@Controller
@SessionAttributes("pet")
public class PetController {
  @RequestMapping(method=GET)
  public Pet get(@RequestParam int id) {
   Pet pet = petService.getPet(id);
   ..
   return pet; // Pet added to Session
  }
  
  @RequestMapping(method=POST)
  public String update(Pet pet, BindingResult result, SessionStatus status) {
    ..
    petService.update(pet);
    
    status.setComplete(); // Remove Pet from session
    ...
  }
}

I did not see an equivalent offering with Jersey MVC.

Security:
As the Spring Security framework is not tightly coupled to Spring MVC, integrating the framework to support the Jersey MVC application is trivial.  On the view tier, Spring Security Tags readily provide access control. If one does not wish to use Spring Security on the web framework, one can easily roll out their own with access being restricted by Jersey filters or Servlet Filters.

Thoughts on Jersey JAX-RS MVC versus Spring MVC:
JAX-RS is a great framework tailored toward creating RESTful web services and Jersey is a solid implementation of the same. As Jersey is a JAX-RS implementation, one could swap out Jersey for another provider like RestEasy if desired without much effort. Spring MVC on the other hand has REST web service support but the same is not a JAX-RS implementation and therefore one is tied to Spring MVC. Read more about a RESTful comparison of Spring MVC and JAX-RS on a very nice INFOQ BLOG

From the perspective of an MVC application, as shown, creating a web application using Jersey is clearly achievable.  It is important to note that one is leaving the JAX-RS specifications and heading into custom Jersey land while doing so though. On the controller tier, I find that the ease of binding Form objects to POJOs is not as full fledged as Spring MVC's offering. The lack of JSR 303 support via automatic validation of Form objects with Jersey MVC is a bit of a downer but not a show stopper. Spring MVC's controller and convention based routing allow for a multitude of return types from a Controller method that Jersey does not seem to have out of the box. Whether the same is a benefit or a pitfall is debatable. 

On the view tier, Spring MVC has strong support for the different templating languages. Be it Free Marker, Velocity, Excel, Jasper Reports, what have you. In addition, Spring MVC out of the box provides a way to chain view resolvers something that Jersey MVC does not have. Spring MVC also comes built in with a rich set of tag libraries supporting JSP, Free Marker and Velocity. There is no such support automatically available via Jersey JAX-RS. Spring MVC also has a strong user community and support in the form of books, forums and blogs working in its favor.

I think back at analogy of designing a bedroom. One can go to a furniture store and simply buy a bedroom set where all components mesh well together, i.e., Spring MVC or one can choose to make the same by buying and building out the components individually, i.e., Jersey MVC. Both approaches will lead one to the same bedroom but how hard was it to get in? When you are in a hurry, the fastest path is welcomed, if you know what I mean ;-) All puns definitely intended ! A colleague of mine also pointed out that Jersey JAX-RS would be driven to make steads in further releases on its core offering, i.e, RESTful services but Spring MVC would make strides on enhancing its web application  support. This is definitely a factor one must consider when deciding between Jersey MVC and Spring MVC.

On the other hand, arguably, if ones application is not very big and a lot of the benefits provided by Spring MVC can be ignored in favor of a light weight MVC application, Jersey MVC can easily fit that role. In particular Jersey MVC will work quite well for web applications that are heavy on Ajax, use client side validation and with partial round trips to the server as they can utilize the strong RESTful support (JSON, XML etc) from Jersey and use the MVC part of Jersey for page transitions.

Condensing, I think Jersey JAX-RS is getting close on the MVC support but for now the Spring MVC star is not extinguished by the Jersey JAX-RS/MVC Juggernaut. If I have not understood the features of Jersey's MVC support correctly, please do comment and clarify the same.

The Jersey MVC Example:
The Jersey MVC Example can be downloaded from HERE. After extracting the file,  execute a "mvn jetty:run" from the root of the project and access the application at http://localhost:8080. The user credentials are the same as in my Spring MVC Security example. Once you get in, play with the validation and scrutinize the source. The example uses Spring for DI.

The styling itself is using Twitter Bootstrap, thanks to a good friend of mine pushing me to try it. I am sadly an average front end developer and therefore offer my thanks to the supremo of web development, Matt Raible, and his customization of App Fuse, based of which, I have been able to change the style of the Flight Application. On Twitter Bootstrap, I did like the ease it presented of creating a decent looking web application but I must lean on Matt's BLOG and his assessment that although Twitter Bootstrap is a great starter template, it is by no means a substitute for a template created by a solid CSS developer.

Sunday, February 12, 2012

Spring Security - Stateless Cookie Based Authentication with Java Config

It has been security time for me recently at work, single sign on and the likes. While at it, I stumbled upon my favorite framework Spring and its offering Spring Security. In the words of the creators of the framework, "Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications".  Spring Security has been around since sometime now but I have not had a chance to use it. This is my first foray into the framework and my BLOG is targeted at accomplishing the following objectives:

1. Enhance the Example Project I created to demonstrate Spring Java Config with Authentication and Authorization powered by Spring Security.
2. Demonstrate an embedded LDAP server in the project as the source of user authentication and user roles.
3. Ensure that the application is stateless thus being able to scale out really easily. Use a  Cookie instead of HttpSession to store the user's authenticated state.
4. Have the application use Form Based Authentication.
5. Use Java Config for Spring MVC and Spring Security

The Example Flight project was augmented with the following ROLE based authorization:

1. Standard User - A user who can view Airports, Search Flights and see reservations
2. Agent - An agent who can perform all the operations a user can with the additional ability to  make reservations on flights
3. Administrator - An administrator who can  do everything a standard user can do with the additional ability to create new Airports for the Flight application. They however cannot make a reservation, i.e., no Agent privilege.

From an LDAP perspective, the following groups can be considered to match the above roles: USER, AGENT and ADMIN.

ApacheDS is one example of an open source LDAP server that can be run in embedded mode. I started looking into how to do the same only to find out that the Spring Security project provides a very easy way to the same. If using Spring Security, the standard way to have an embedded server in your application for demonstration or testing purposes is to simply have the following line defined in your spring beans.xml. krams BLOG on using embedded LDAP with Spring MVC was a major help in gettting the code functional:
 <--ldiff file to import -->
 <ldap-server root="o=welflex" ldif="classpath:flightcontrol.ldiff" />

The above claim seems exotic but the presence of the above line and the magic of  Springs Extensible XML Authoring has an embedded LDAP going with minimal developer effort. The Java Config equivalent of the same is shown below where the container is programatically created:
@Configuration
public class SecurityConfig {
  /**
   * This bean starts an embedded LDAP Server. Note that start
   * is not called on the server as the same is done as part of the bean life cycle's
   * afterPropertySet() method.
   *
   * @return The Embedded Ldap Server 
   * @throws Exception
   */
  @Bean(name = "ldap-server")
  public ApacheDSContainer getLdapServer() throws Exception {
    ApacheDSContainer container = new ApacheDSContainer("o=welflex",
        "classpath:flightcontrol.ldiff");
    container.setPort(EMBEDDED_LDAP_SERVER_PORT);
    return container;
  }
...
}
With the above Java Config, the embedded LDAP server is primed with the contents from the flightcontrol.ldiff file.

For the Stateless requirement, the flight control application will rely on a Cookie on the client browser to detect the user that is logged in rather than use the HTTP Session. Spring Security tends to gravitate toward using the HTTP Session. However as of Spring 3.1, they introduced a configuration of "stateless".  The setting of stateless meant that a HTTP session would not be created by Spring Security. The same however does not translate into a Cookie based authentication mechanism being introduced. Using name spaces, one would bootstrap spring security for the application as shown below:
  <http auto-config="true" create-session="stateless">
      <-- Allow anon access -->
      <intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
      <intercept-url pattern="/logoutSuccess*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
      <intercept-url pattern="/scripts*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
      <--Enforce user role -->
      <intercept-url pattern="/*" access="ROLE_USER" />

      <-- Form login, error, logout definition -- >
      <form-login login-page="/login.html"
    always-use-default-target="true" default-target-url="/home.html"
     authentication-failure-url="/login.html?login_error=1" />
          logout logout-url="/logout" logout-success-url="/logoutSuccess.html" />
  </http>
In order to understand how the above Spring Security namespace is translated to Java Beans, take a look at the BLOG by Luke Taylor on the same. The above will work fine if one is using Basic or Digest authentication to secure resources but does not work with form based authentication and a stateless environment. If you wish to use Basic or Digest based authentication, then take a look at baeldung's BLOG on the same.

As the requirement of the flight application is to use form based login via Cookie Support, a filter is  created that is a substitute for the SessionManagementFilter:
public class CookieAuthenticationFilter extends GenericFilterBean {

  public CookieAuthenticationFilter(LdapUserDetailsService userDetailService,
      CookieService cookieService) {...}

  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
    ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    SecurityContext contextBeforeChainExecution = loadSecurityContext(request);
    
    // Set the Security Context for this thread
    try {
      SecurityContextHolder.setContext(contextBeforeChainExecution);
      chain.doFilter(request, response);
    }
    finally {
      // Free the thread of the context
      SecurityContextHolder.clearContext();
    }
  }

  private SecurityContext loadSecurityContext(HttpServletRequest request) {
    final String userName = cookieService.extractUserName(request.getCookies());

    return userName != null
        ? new CookieSecurityContext(userDetailService.loadUserByUsername(userName))
        : SecurityContextHolder.createEmptyContext();
  }
}
In the above code, the loadSecurityContext method is responsible for loading user information from the authentication provider. The method will attempt to obtain the authenticated principal from the custom user cookie set and if present, create a Spring SecurityContext and set the same in the SecurityContextHolder. Setting of the Context will ensure that no further authentication is performed and the requested resource will be served up. If the User security cookie were not present, then an empty context is provided so that filters further downstream can re-direct the request to a login page.

So where does the User Cookie get set? After a successful authentication, an AuthenticationSuccessHandler is invoked by Spring Security's UsernamePasswordAuthenticationFilter and the former is where the cookie gets set:
public class AuthSuccessHandler implements AuthenticationSuccessHandler {
  ... 
  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
    Authentication authentication) throws IOException, ServletException {
    SecurityContext context = SecurityContextHolder.getContext();
    Object principalObj = context.getAuthentication().getPrincipal();
    String principal = ((LdapUserDetails) principalObj).getUsername();
    
    // Create the User Cookie        
    response.addCookie(cookieService.createCookie(principal));
    response.sendRedirect("/home.html");
  }
}
The UserNamePasswordAuthenticationFilter is notified of the custom AuthenticationSuccessHandler as shown below:
@Configuration
public class SecurityConfig {
  ....
  private UsernamePasswordAuthenticationFilter getUserNamePasswordAuthenticationFilter() {
    UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter();

    filter.setAllowSessionCreation(false);
    filter.setAuthenticationManager(getAuthenticationManager());
    // Set the Auth Success handler
    filter.setAuthenticationSuccessHandler(new AuthSuccessHandler(getCookieService()));
    filter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/login.html?login_error=1"));
    
    filter.setFilterProcessesUrl("/j_spring_security_check");

    return filter;
  }
}
The final chain of Filters is declared as:
@Configuration
public class SecurityConfig {
  ....
  @Bean(name = "springSecurityFilterChain")
  public FilterChainProxy getFilterChainProxy() {
    SecurityFilterChain chain = new SecurityFilterChain() {

      @Override
      public boolean matches(HttpServletRequest request) {
        // All goes through here
        return true;
      }

      @Override
      public List<Filter> getFilters() {
        List<Filter> filters = new ArrayList<Filter>();

        filters.add(getCookieAuthenticationFilter());
        filters.add(getLogoutFilter());
        filters.add(getUserNamePasswordAuthenticationFilter());
        filters.add(getSecurityContextHolderAwareRequestFilter());
        filters.add(getAnonymousAuthenticationFilter());
        filters.add(getExceptionTranslationFilter());
        filters.add(getFilterSecurityInterceptor());

        return filters;
      }
    };
    
    return new FilterChainProxy(chain);
  }
}
With the above configurations, the application has all the necessary ingredients to provide Cookie based authentication and Role based authorization. The following HTML snippets demonstrate how Spring Security's taglibs are used to honor the roles on the view tier of the architecture:
<-- Airports page -- >
<sec:authorize ifAllGranted="ROLE_ADMIN">
   <-- Display the form to add an airport -- >
</sec:authorize>

<-- Flight Search page. Display column to book flight only for AGENTs -->

<display:table name="flightSearchResult.flights" class="table"
 requestURI="" id="flight" export="true" pagesize="10">
         .....
 <sec:authorize ifAllGranted="ROLE_AGENT">
  <display:column title="" sortable="false" href="/bookFlight.html"
   paramId="id" paramProperty="id" titleKey="flightId">
           Book
        </display:column>
    </sec:authorize>
</display:table>
Individual methods of the Service classes can also be secured for authorization using Spring Security via annotations. The examples does not get into the same.

Conclusion

The example provided uses Java Config in its entirety and can give an entrant into Spring Security an idea of how the request chain is set up simply by following the Java Config. The beauty of the Spring Security framework lies in the fact that authentication and authorization details are set up within the filter chain and clearly remove boiler plate from a developer who is working of the Controller tier. Spring's Security does not have to stop at the view tier and can be used to authorize access to to Service tier methods as well.

The example obtains the user roles from the embedded LDAP server on every request. The can be performance issue. Consider not prematurely optimizing as LDAP look ups are supposed to be rapid. If you do face a problem with performance, consider a backing cache. Also note that the user cookie created is not secure and can easily be spoofed. In an actual implementation one would use some way to identify against spoofed cookies. 

Download the full source code as a maven example from here and once extracted, execute a "mvn jetty:run" to start the same. All the security configuration is set up in the package com.welflex.web.security. You will see an embedded LDAP server start and the corresponding schema imported into the server. Access the web application at http://localhost:8080.

When prompted to login use one of the following user name/password combinations to see the different roles and corresponding access control in action:

1. Admin User - sadmin/pass
2. Agent User - sagent/pass
3. Standard User - suser/pass

Investigate your browsers cookies to see that a USER cookie has been set by the application and that there is no sign of JSESSIONID cookie.

I hope this is of help to someone trying to integrate Spring Security into their application and wants to use form based login with Cookies to remember the user. There have been some Stack Overflow and Spring Security Forum postings asking about the same.

There are still areas to explore with the Spring Security domain like Spring Security Oauth, Spring Security SAML (empty page)Spring Security CAS.

Saturday, January 28, 2012

Spring MVC 3.1 with Jamon Templating

Quite clearly as my BLOGs show, I have been working with my favorite technology stack recently, i.e., Spring. In particular, I have been working on Spring MVC and am looking at finding the right view technology to use with Spring. I am biased toward FreeMarker as it appears to be a super set of Velocity and can work with JSPs if required. That said, I have noticed on some Spring Forum postings queries on using Jamon with Spring.  There does not appear to be a concrete example of the same on the web. There are many that talk about performance monitoring of Spring with its namesake JAMon however. So here goes my attempt at integrating Spring with Jamon.

So what is Jamon? Quoting the words of the creators of Jamon, "Jamon is a text template engine for Java, useful for generating dynamic HTML,XML, or any text-based content. In a typical Model-View-Controller architecture, Jamon clearly is aimed at the View (or presentation) layer".

One of the constructs that is central to Jamon is type safety. Jamon on the view tier provides compile time type safety that is quite lost when using for example, JSPs, and the expression language libraries that are associated with it.

With technologies like JSP, errors are detected by a developer at runtime and they fix the same as they develop the application. Detecting an error at compile time however is really beneficial if the cost of starting an application and testing a request path is significant.Jamon templating with the compile time type safety it provides the presentation tier, mitigates the turn around time for development and refactoring. I will not delve into the details of Jamon as the same can be read on the Jamon website.

An interview on the web with one of the creators of Jamon describes how templating languages like FreeMarker and Velocity only partially fill the void of type safety when working with a framework like Spring MVC and infact have a hole that can lead to non type safe behavior.

Consider the following snippet using Spring MVC with FreeMarker for rendering the view:
@Controller
public class LoginController {
  public ModelAndView login(User user, BindingResult result) {
     ModelAndView mav = new ModelAndView("user");
     ......
     if (result.hasErrors()) {
       mav.addObject("user", user); 
       ....
       return mav;
     }
     ...
  }
}
The corresponding FreeMarker template, login.ftl, might look like:
 <@spring.bind "user.*"/>
 <@spring.formInput "user.username", id="username"/>
With the above, all is well and the runtime binding works just fine. However, if a developer accidentally forgot to:
  • Add the user object to the model
  • Or misspelled the "key" to the user object as "user" but as "users"
  • Or misspelled "user.username" on the FreeMarker template as "user.usrname"
  • Or placed a wrong type in the value for the ModelAndView instead of the User object
They would experience failures at runtime and even a strong templating language like FreeMarker would be powerless to detect the issues mentioned due to the loose coupling between the Spring MVC controller and the Template. Objects added to the ModelAndView object are of signature addObject(String, Object), ie., quite a few rooms for accidents. This decoupling nature of Spring MVC would hurt even a presentation tier written using Jamon right? Well would it really ? What if  type safety could be maintained all the way from the Spring Controller tier to the view tier with Jamon? Lets say for the sake of discussion, we desire to render a login page using Jamon with Spring MVC.  A Jamon Template for the user login titled LoginView.jamon is shown below in which the User object is explicitly passed in to the Jamon template. There are no iffs or butts regarding what is available to the Template here, it is the User object and only the User object that is made available to the template. It is possible to pass in null due to a programming mistake or runtime time error in which case all bets are off and this concern transcends compile time safety. At compile time a LoginView.class is made available:
 <%import>
com.welflex.model.User;
</%import>
<%args>
User user;
</%args>

<form....
    ...
    <input type="text" id="userName" name="userName" value="<% user.getUserName() %>">
    ....
    <input type="submit" name="Login" value="Login"/>
 </form>
The Login Controller is designed to return a Jamon Renderer rather than a ModelAndView as shown below:
@Controller
public class LoginController {
  /**
   * @return Return a Jamon Renderer
   */
  @RequestMapping(value = "/login.html", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
  @ResponseBody
  public Renderer login() {
    User user = new User("Enter user name", "Enter password");
    return new LoginView().makeRenderer(user);
  }
}
Nice and dandy, so how does one tell Spring MVC to handle the Jamon Renderer? Look no further than below where a custom HttpMessageConverter is created for the same:
public class JamonTemplateHttpConverter extends AbstractHttpMessageConverter<Renderer> {

  @Override
  protected boolean supports(Class<?> clazz) {
   // Only Renderer classes are supported by this HttpMessageConverter
   return Renderer.class.isAssignableFrom(clazz);
  }
  
  @Override
  public boolean canWrite(Class<?> clazz, MediaType mediaType) {
    return supports(clazz) && MediaType.TEXT_HTML.equals(mediaType);
  }
  ...

  @Override
  protected void writeInternal(Renderer t, HttpOutputMessage outputMessage) throws IOException,
    HttpMessageNotWritableException {
    Charset charset = getContentTypeCharset(outputMessage.getHeaders().getContentType());
    t.renderTo(new OutputStreamWriter(outputMessage.getBody(), charset));
  }
  ...
}
Of particular note in the above class is the fact that it knows how to handle Jamon Renderers and also writes the renderer's content to the HttpServlet output stream. The next step involves letting Spring know of the renderer. This operation is accomplished in the Web Configuration class as shown below:
@EnableWebMvc
@Configuration
@Import({ControllerConfig.class})
public class WebConfig extends WebMvcConfigurerAdapter {
  ...  
  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(new JamonTemplateHttpConverter());
  }
  ...
}
The above is one way where type safety is preserved using Jamon and Spring MVC. What about if one wishes to use the ModelAndView paradigm from Spring as is standard practice ? Well I could not do the same ! At least not without some customizations. Spring Dispatcher Servlet is strongly tied to the ModelAndView class for its functioning and sadly ModelAndView is not an interface. However, the good thing is that that ModelAndView is not "final" and neither are its methods. In addition, the View part of ModelAndView is an interface so we start by creating a custom implementation of the View whose primary purpose is to render the contents:
public class JamonView implements View {
  private final Renderer renderer;
  
  public JamonView(Renderer renderer) { this.renderer = renderer; }
  
  @Override
  public String getContentType() { return MediaType.TEXT_HTML_VALUE; }

  @Override
  public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {  
    // Note that the Model is never used at all here.
    StringWriter writer = new StringWriter();
    renderer.renderTo(writer);
    response.getOutputStream().write(writer.toString().getBytes());
  }
}
The ModelAndView object is what is central to Spring's DispatcherServlet and as one would probably guess, the only option I had at my disposal (no cglib enhancements please) was to extend ModelAndView as shown below:
public class JamonModelAndView extends ModelAndView {  
  
  public JamonModelAndView(Renderer renderer) { super(new JamonView(renderer)); }
  
  public JamonModelAndView(JamonView view) { super(view); }
  
  // Probably want to ensure that other methods are not invokable by throwing UnsupportedOperationException
  // Sadness that ModelAndView is not an interface or one could use dynamic proxies! Also there is no 
  // higher level abstraction one can use
}
On could also have the JamonModelAndView be a static static class that provided methods to create a ModelAndView with signatures that accept a Renderer or JamonView. With the custom extension to ModelAndView, a resulting Controller class for the Login operation would look like the following where two separate execution paths are demonstrated, one for a successful login and a second where validation errors were detected. God bless Liskov and his substitution principle Also note that the User object is automatically bound and its properties validated with values passed in from the form:
@Controller
public class LoginController {
  ....
  @RequestMapping(value="/login.html", method = RequestMethod.POST)
  public ModelAndView login(@Valid User user,  BindingResult result,  Map<String, Object> model) {
   return result.hasErrors() ?  new JamonModelAndView(new LoginView().makeRenderer(user, result))
      : new ModelAndView("redirect:/welcome.html");    
  }
  
  @RequestMapping(value="/welcome.html")
  public ModelAndView welcome() {
    return new JamonModelAndView(new WelcomeView().makeRenderer());
  }
}
With the above, we are all but done with a type safe rendering approach using Spring MVC and Jamon. What remains is the part where form submission and the input variable mapping has to be defined in the Jamon Template. If one does the following where the userName property is quoted as a non type safe string, we are left with a hole all over again regarding our type safe mantra:
<form....
    ...
    <input type="text" id="userName" name="userName" value="<% user.getUserName() %>">
    ....
    <input type="submit" name="Login" value="Login"/>
 </form>
I have broken my head trying to figure out a type safe way to describe how to specify the input form mappings in a type safe way and ended up with a cheap solution that requires the definition of a constant somewhere that describes the same. Please note that the constant itself is not safe from any refactoring done on the User bean as it not strongly typed to the actual method signature of setUserName(User):
<form....
    ...
    <input type="text" id="userName" name="<% User.USER_NAME_PROPERTY %>" value="<% user.getUserName() %>">
    ....
    <input type="submit" name="Login" value="Login"/>
 </form>
Running the Example:

A simplistic application demonstrating a Login Form with validation is available for download here. Extract the same and execute a "mvn jetty:run" to launch the application. Access the application at http://localhost:9090 and login using any username/pass combo to a simple welcome page. If you are an eclipse user, install the eclipse plugin for Jamon for syntax highlighting and IDE support. I would recommend that any user trying this example attempt to change code and witness for themselves the benefits of compile time type safety that Jamon provides. Please note that if you use the J2EE perspective on your project, you will not be able to see the Jamon configuration options sadly. On the Java perspective however, all is visible when you goto Project->Properties->Jamon.

Conclusion:

The question remains whether Jamon is a suitable candidate for the presentation tier when using something like Spring MVC? My answer as any smart architect would say is, it depends! If the web application is primarily a read-only, i.e, whose focus is to render data for display, then yes, you cannot go wrong with the benefits of Jamon. Where Jamon for the view tier suffers is when an application has a lot of forms requiring user input and the fact that there is no way to guarantee type safety of the input variables without the use of constants as shown above. The mantra of type safety is only partial in such cases and if this is something you are willing to tolerate, more power to you. Jamon cannot be faulted for this deficiency as the Java language itself has no way of describing the property names in a type safe manner. In addition, Jamon does not provide an expression language or tag based support from what I know of. Jamon has a lot going for it and I have personally developed a couple of applications using it for my view tier. Features like macros provided by FreeMarker make development easier and if one is careful and thorough with good unit/automation/manual coverage of ones application, the fear of runtime errors due to lack of type safety can be mitigated in favor of the powerful EL and Macro support provided by the other view technologies for Spring MVC. In addition, there is strong integration support from the Spring Framework for FreeMarker and Velocity with provided macros etc. If any person who stumbles on this BLOG has used FreeMarker or Velocity with Spring, I would like to hear of their experience of same please.In addition, if anyone has integrated their Spring MVC application with Jamon in different way, I'd love to hear the approach.

Lets get the bottom line straight though, Jamon, FreeMarker, Velocity, whatever, in the end remember the following:

Developing with Spring my friends is a fine thing....
Your code will sing, and your projects will fly to successful wins as if they had wings....
There just ain't no going wrong with this thing....
It's not just some temporary fling....
Embrace it, and it will treat you like a king!

Peace!

Sunday, January 8, 2012

Spring 3.1 MVC Example

I started Sleepless in Salt Lake City with an example of Spring MVC that used auto-wiring with Spring 2.5. Sadly, I have lost that code. On the bright side however, Spring has made some advances that I am hoping to catch up with a re-vamp of the original BLOG. This BLOG primarily hopes to demonstrate the use of Spring Java Config spanning different tiers of an application with a simple Spring MVC 3.1 example that one can use for learning as well.

Spring JavaConfig is a means of configuring the Spring Container using pure-java, i.e., without XML if one so desired. It relies on the features of Java 5.X+ such as Generics and Annotations to express what was previously done via XML. Java Config has the following advantages:

1. Injections, as it should be done using features like inheritance, polymorphism, etc.
2. Full control on creation and initialization of beans.
3. Makes refactoring easy without the need for something like Spring IDE
4. Ability to refrain from Classpath scanning as that can be expensive for container initialization
5. Use XML or property support in conjunction if desired

Most of this BLOG is in the form of code with a functional examples provided as well for download and execution. The code shown below assumes that a person is familiar with Spring MVC and does not delve into the basics of the same. The examples used in this BLOG are written with the following objectives:

1. Demonstrate Spring Java Config across the different tiers with no spring XML usage
2. Demonstrate transaction management
3. Demonstate a validator for the beans using JSR-303
4. Demonstate the REST features of Spring XML by having the application double as a RESTful Web Service.
5. Demonstate how Unit testing can be achieved across the tiers when using Java Config
6. Demonstates use of RestTemplate in an integration-test of the Web Service

In short, the making of a really long POST ;-)

The app references in this BLOG is a simple Flight reservation system where flights can be searched and booked. The web application itself is separated into 3 tiers, Web, Service and Data Access. Each of the tiers has its own Java Configuration as shown below with the WebConfig being the aggregator or top level Config:
With the interest of making unit testing easier, the Config classes are separated via interface/impl.

The data access tier defines a Java Config module as shown below:
@Configuration
@EnableTransactionManagement
public class DefaultDaoConfig implements DaoConfig, TransactionManagementConfigurer {
  
  // Dao Initialization
  @Bean
  public FlightDao getFlightDao() {
     return new FlightDaoImpl(getSessionFactory());
  }
   ...other DAOs

  // Session Factory configuration for Hibernate
  @Bean
  public SessionFactory getSessionFactory() {
    return new AnnotationConfiguration().addAnnotatedClass(Ticket.class)
      .addAnnotatedClass(Flight.class).addAnnotatedClass(Airport.class)
      .configure().buildSessionFactory();
  }

  // Transaction manager being used
  @Override
  public PlatformTransactionManager annotationDrivenTransactionManager() {
    return new HibernateTransactionManager(getSessionFactory());
  }
}

Of interest in the above is the @EnableTransactionManagement annotation which enables Spring's annotation driven transaction management capabilities for services annotated with @Transactional. The @Transactional annotation instructs the Spring container to provide transactional semantics for the method.  A service class annotated with @Transactional is shown below. Also note that the FlightDao and TicketDao beans are defined to be set explicitly via the constructor without the use of the @Autowired annotation. @Autowired could be used as well if desired for having a no-args constructor with the Spring Framework reflectively initializing the DAOs.

@Transactional(readOnly = true)
public class ReservationServiceImpl implements ReservationService {
  private final FlightDao flightDao;
  private final TicketDao ticketDao;

  public ReservationServiceImpl(FlightDao flightDao, TicketDao ticketDao) {...}

  @Override
  @Transactional(rollbackFor = { NoSeatAvailableException.class }, readOnly=false)
  public Ticket bookFlight(Reservation booking) throws  NoSeatAvailableException {
   ...
  }

  @Override
  public List<Ticket> getReservations() {...}
}

The Services tier also has a corresponding Config where the Services of the application are defined:
@Configuration
public class DefaultServiceConfig implements ServiceConfig {
  @Autowired
  private DaoConfig daoConfig;

  @Bean
  @Override
  public AirlineService getAirlineService() {
    return new AirlineServiceImpl(daoConfig.getFlightDao(), daoConfig.getAirportDao());
  }
  .........other services ...
}

One might ask the question as to how can one mock out the DaoConfig for testing purposes as it is set to be auto-wired, surely not reflection? Well, on the Configs one cannot use constructor based initialization as Spring's container expects a no-arg constructor. One can however define a setter for the Config and be able to mock the same out. The following sample of the ControllerConfig demonstrates the same:
@Configuration
public class ControllerConfig {
  private ServiceConfig serviceConfig;
  
  @Autowired 
  public void setServiceConfig(ServiceConfig serviceConfig) {
    this.serviceConfig = serviceConfig;
  }
 
  @Bean
  public FlightsController getFlightController() {
    return new FlightsController(serviceConfig.getAirlineService(), serviceConfig.getAirportService());
  }
  ... other controllers...
}
The FlightController is shown below:
@Controller
public class FlightsController {
  private final AirlineService airlineService;
  private final AirportService airportService;

  public FlightsController(AirlineService airlineService, AirportService airportService) {...}

  // Flight search page initialization
  @RequestMapping(value = "/searchFlights.html", method = RequestMethod.GET)
  public ModelAndView searchFlights() throws Exception {
    List<Airport> airports = airportService.getAirports();

    ModelAndView mav = new ModelAndView("searchFlights");

    mav.addObject("airports", airports);

    return mav;
  }

  // Searching for a flight. Note that the Critiera object is automatically bound with 
  // the corresponding form post parameters
  @RequestMapping(value = "/searchFlights.html", method = RequestMethod.POST)
  public ModelAndView searchFlights(FlightSearchCriteria criteria) throws Exception {

    ModelAndView mav = new ModelAndView("searchFlights");
     ....
    FlightSearchResults searchResult = airlineService.getFlights(criteria);

    mav.addObject("flightSearchResult", searchResult);

    return mav;
  }
}

Annotating a bean with @Controller indicates to Spring that the same is part of the MVC family and to use the same for mapping request urls and servicing web requests. A few other things to note about the controller:

1. Does not need to extend any particular base class
2. The @RequestMapping annotation defines the HTTP Method and resource serviced. In the example shown, "/searchFlights" responds differently to GET and POST requests

All these tier configurations are wired together via WebConfig which also defines the different components required to setup the Spring MVC Servlet. The @Import annotation indicates to the Spring Container which Config's need to be included. Note the same can also be done in the web.xml as part of the Servlet definition if so desired.
@EnableWebMvc
@Configuration
@Import({ ControllerConfig.class, DefaultServiceConfig.class, DefaultDaoConfig.class })
public class WebConfig extends WebMvcConfigurerAdapter 
// Validator for JSR 303 used across the application
  @Override
  public Validator getValidator() {...}

 // View Resolver..JSP, Freemarker etc
  @Bean
  public ViewResolver getViewResolver() {...}

 // Mapping handler for OXM
  @Bean
  public RequestMappingHandlerAdapter getHandlerAdapter() {.. }
 
 @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
  }
}
The annotation @EnableWebMvc is required to tell Spring that this is a MVC application. Implementing the WebMvcConfigurerAdapter allows for customization the Spring Servlet and path handling. Alternatively, one could also extend WebMvcConfigurationSupport directly and provide the necessary customization

Validation of Requests using JSR-303 Bean Validation API:

JSR-303 standardizes the validation for the Java Platform. Use it if you wish for validation. The annotations from the API are used to specify validation constraints and the runtime enforces the same. As this example utilizes Hibernate, adding Hibernate-Validator which is an implementation of the API is a natural choice. In the example provided the Reservation class is annotated with the annotations from the JSR to provide runtime validation and messages. The messages could be obtained from a resource bundle if desired:
public class Reservation {
  @XmlElement
  @NotBlank(message = "must not be blank")
  private String reservationName;

  @Min(1)
  @XmlElement
  private int quantity = 1;

  @XmlElement
  @NotNull(message = "Flight Id must be provided")
  private Long flightId;
  ....
}
The web deployment descriptor is where the application converges and  the DispatcherServlet is notified of the Context class to use and the location of the WebConfig. As previously mentioned, it is possible to provide a comma separated list of Configs in the web.xml if desired versus importing them in the WebConfig:
<web-app>
        <servlet>
                <servlet-name>springExample</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet
                </servlet-class>
                <init-param>
                        <param-name>contextClass</param-name>
                        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
                        </param-value>
                </init-param>
                <!-- Tell Spring where to find the Config Class
                     This is the hook in to the application. -->
                <init-param>
                        <param-name>contextConfigLocation</param-name>
                        <param-value>com.welflex.web.WebConfig</param-value>
                </init-param>
                <load-on-startup>1</load-on-startup>
        </servlet>
        ....
</web-app>

Unit Testing:

Unit testing the tiers is very easily supported by the Spring Testing framework. When testing the service layer for example, one does not really need to integrate with the database and the corresponding interactions can be mocked out. For this reason, the objects in the DAO config are provided as mocks as shown below:
@Configuration
@EnableTransactionManagement
public class MockDaoConfig implements DaoConfig {
 
  @Bean
  public FlightDao getFlightDao() {
    return Mockito.mock(FlightDao.class);
  }
  ..// Other mocks
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MockDaoConfig.class,
    DefaultServiceConfig.class }, loader = AnnotationConfigContextLoader.class)
public class AirportServiceTest {
  @Autowired
  private AirportDao airportDaoMock;

  @Autowired
  private ApplicationContext ctx;

  @Test
  public void getAirportCode() {
    // Obtain Airport service from the context
    AirportService a = ctx.getBean(AirportService.class);

    // Alternatively, instatiate an Airport Service by providing a mock
    AirportService a2 = new AirportServiceImpl(airportDaoMock);
  }
  ...
}
In the above test, the Config's being used are the concrete implementation of ServiceConfig and a mock of DaoConfig. This enables the testing of the Service tier by mocking the Data access tier. Some people prefer to test each class in isolation  by wiring the same up with the required dependencies explicitly while others prefer to obtain the class from the container with all dependencies wired up. The choice of style of testing is a topic for another BLOG but it is sufficient to accept that either style is supported. It is to be noted that one does not need to mock all the beans for testing and can define specific Config objects as required. As with the Service tier mocking out the Data Access tier, the  Controller tier can also be tested by mocking out the Service tier objects.

Spring MVC Restful Services:
 
One of the goals of this example was to demonstrate how the web application doubles as a service as well. Consider the following controller which provides representations for the web application and a service consumer:
@Controller
public class ReservationsController {
  private final AirlineService airlineService;
  private final ReservationService reservationService;

  public ReservationsController(ReservationService reservationService, AirlineService airlineService) {...}

  @RequestMapping("/reservations.html")
  public ModelAndView getReservationsHtml() {...}

  @RequestMapping(value = "/reservations/{reservationId}.html", method = RequestMethod.GET)
  public ModelAndView getReservationHtml(@PathVariable Long reservationId) {...}

  // Web Service Support to provide XML or JSON based of the Accept Header attribute
  @RequestMapping(value = "/reservations", method = RequestMethod.GET, produces = {
      MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
  @ResponseBody
  public Reservations getReservations() {...}

  @RequestMapping(value = "/reservations/{reservationId}", method = RequestMethod.GET, produces = {
      MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
  @ResponseBody
  public Ticket getReservation(@PathVariable Long reservationId) {...}
  ....
}
In the above shown controller, the getReservationsHtml() returns a HTML representation of the reservations while the call to getReservations() returns an XML or JSON representation of the reservations. The type of representation returned depends on the Accept header provided to the service. The @ResponseBody annotation indicates that a view is not targetted but that the resulting object should be translated directly. The example itself uses Spring OXM for marshalling and unmarshalling XML via JAXB. An integration test for the above controller using RestTemplate is shown below:
public class WebServiceIntegrationTest {
  private RestTemplate template;
  private static final String BASE_URL = "http://localhost:9091";

  @Before
  public void setUp() {
    // Create Rest Template with the different converters
    template = new RestTemplate();
    List<HttpMessageConverter<?>> converters = ...;
    template.setMessageConverters(converters);
  }

  private static final String FLIGHT_NUMBER = "LH 235";

  @Test
  public void reservations() {
    Flight singleFlight = template.getForObject(BASE_URL + "/flights/" + FLIGHT_NUMBER,
      Flight.class);

    Reservation res = new Reservation();
    res.setFlightId(singleFlight.getId());
    res.setQuantity(10);
    res.setReservationName("Sanjay Acharya")

   // Post to create a ticket
    Ticket ticket = template.postForObject(BASE_URL + "/bookFlight", res, Ticket.class);
    assertNotNull(ticket);
    System.out.println("Ticket reserved:" + ticket);

    // All Reservations
    Reservations reservations = template.getForObject(BASE_URL  + "/reservations", Reservations.class);
    assertTrue(reservations.getTickets().size() == 1);

    // Single reservation
    assertNotNull(template.getForObject(BASE_URL + "/reservations/" + ticket.getId(), Ticket.class));
  }
}

For more information on the RestTemplate, check out my other BLOG on Rest Client Frameworks.

Side Note:

In this example, I have used a framework called Pojomatic for the convenience it provides in implementing equals(), hashCode() and toString() for my POJOs. I prefer its brevity over using the the tools provided by the Apache commons project which I have used in my previous BLOGs. Check the same out.

Running the Example:

The example provided herewith demonstrates the Flight Spring MVC example. It uses an in memory database which is primed with data on start up. The model package in the example is overloaded as far as its responsibilities go. The POJO's there in serve as database model objects and data transfer objects. The example, unit tests or integration tests are by no means designed to be comprehensive and are only present only for demonstration purposes.

1. Download the example from HERE
2. Execute a mvn jetty:run to start the application.
3. Execute a mvn integration:test to see the Web Service calls being exercised
4. The Flight Web Application is available at http://localhost:8080
5. Web service url's can be accessed directly via:   http://localhost:8080/reservations , http://localhost:8080/reservations/{id}, http://locahost:8080/flights, http://localhost:8080/airports

Conclusion:

I find the clarity and control of object initialization and wiring really convenient with Spring Java Config. Walking the dependency tree is also very intuitive. In addition, due to the strong typing, refactoring is made easy even without a tool like Spring IDE. What I like about Spring MVC versus other web frameworks is its simplicity with the Front Controller/Dispatcher pattern. One can use whatever Ajaxian technology they like to enhance the user experience. The framework itself is very non-invasive, i.e., it does not require the use of Spring across all the tiers. The Restful support facilitates easy interaction with Ajax based technologies and makes the web app a true resource based system. I do not use Spring MVC on any production application sadly. If anyone who does have experience with the same stumbles upon this BLOG, I would love to hear of the same.

Take a look at the Spring Security Stateless Cookie Authentication BLOG for an example of the same MVC application but using Twitter Bootstrap and integrated with Spring Security.

Update - I have uploaded a simple presentation that I gave along with supporting code. You can view the same at Spring MVC 3.1 Presentation/Tutorial.