Search This Blog

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.

Tuesday, January 3, 2012

Apache ZooKeeper - A maven example

Let me begin with - Happy New Year! I am starting this years BLOG entry with some playing I did over the holidays with Apache ZooKeeper. So what is Apache ZooKeeper?  Broadly put, ZooKeeper provides a service for maintaining distributed naming, configuration and group membership. Zookeeper provides a centralized coordination service which is distributed, consistent and highly available. In particular, it specializes in coordination tasks such as leader election, status propagation and rendezvous. Quoting the ZooKeeper documentation, " The motivation behind ZooKeeper is to relieve distributed applications the responsibility of implementing coordination services from scratch."

Zookeeper facilitates the coordination of distributed systems via a hierarchical name space called ZNodes. A ZNode can have children Znodes as well as have data associated with it (figure linked from official ZooKeeper documentation):

ZooKeeper also has the concept of Nodes and Ephermeral Nodes. The former survives the death of the client that created it while the latter does not. Nodes can also be SEQUENTIAL where a SEQUENCE number is associated with Node. Sequences clearly lend themselves for queue type or ordered behavior when required. ZNodes cannot be deleted as long as they have children under it.

The Zookeeper API itself it a very simple programming interface that contains methods for CRUD of a ZNode and data along with a way to listen for changes to the node and/or its data.

One can read quite a bit about Zookeeper from their documentation and I will not delve into details. My goal in this BLOG is to provide some simple examples of how Zookeeper can be used for:

1. Leader Election
2. Rendezvous or Barrier

1. Leader Election Example:

As mentioned previously, Zoo Keeper specializes in  Leader Election, where a particular server of a type is elected the leader and upon its demise, another stands up to take its place. The concept of Ephemeral nodes is pretty useful in such a scenario where a service upon start up registers itself as a candidate in the pool of resources to be used. For the sake of discussion, consider an Echo Service with the fictional constraint that there can be only one Echo Service at any given time servicing requests but should that robust service die, another one is ready to resume the responsibility of servicing clients. The EchoService on start up registers an ephemeral node at "/echo/n_000000000X". It further registers a watcher on its predecessor Echo Service, denoted by the ZNode,  "/echo/n_000000000X-1", with the intent that should the predecessor die, then the node in question can assume leadership if it is the logical successor as shown in the picture below:
Leader Election of Echo Server



The reason for registering a watch on the predecessor versus the root of "/echo" is to prevent herding as described in the Zookeeper recipes. In other words in the event of  a leader being decommisioned, we wouldn't want all the Echo Server leadership contenders to stress the system by requesting ZooKepper for the children of the "/echo" node to determine the next leader. With the chosen strategy, if the predecessor dies, then only its follower is the one that executes the call to get the children of "/echo". The example provided herewith spawns two Echo Servers and has a client that calls the server. One of the two servers is considered the leader and assumes the responsibility of servicing the requests of the client. If the leader dies, then the successor Echo Server assumes leadership and starts servicing client requests. The client will connect to the next leader automatically upon the death of the current leader. The Echo Server code is shown below:
public class EchoServer extends Thread implements IZkDataListener, IZkStateListener {
  private ZkClient zkClient;
  // My ZNode
  private SequentialZkNode zkNode;

  // My leader ZNode
  private SequentialZkNode zkLeaderNode;
  private ServerSocket serverSocket;
  
  // Port to start server on
  private final Integer port;
  private final List<SlaveJob> slaves;
  private final Object mutex = new Object();
  private final AtomicBoolean start = new AtomicBoolean(false);
  private final Random random = new Random();

  public EchoServer(int port, int zkPort) {
    this.port = port;
    this.zkClient = new ZkClient("localhost:" + zkPort);
    this.slaves = new ArrayList<SlaveJob>();
  }

  @Override
  public void run() {
    try {
      // Sleep for some randomness leader selection
      Thread.sleep(random.nextInt(1000));

      // Create Ephermal node
      zkNode = ZkUtils.createEphermalNode("/echo", port, zkClient);

      // Find all children
      NavigableSet<SequentialZkNode> nodes = ZkUtils.getNodes("/echo", zkClient);

      // Find my leader
      zkLeaderNode = ZkUtils.findLeaderOfNode(nodes, zkNode);

      // If I am leader, enable me to start
      if (zkLeaderNode.getPath().equals(zkNode.getPath())) {
        start.set(true);
      } else {
        // Set a watch on next leader path
        zkClient.subscribeDataChanges(zkLeaderNode.getPath(), this);
        zkClient.subscribeStateChanges(this);
      }

      synchronized (mutex) {
        while (!start.get()) {
          LOG.info("Server on Port:" + port + " waiting to spawn socket....");
          mutex.wait();
        }
      }
      // Start accepting connections and servicing requests 
      this.serverSocket = new ServerSocket(port);

      Socket clientSocket = null;
      
      while (!Thread.currentThread().isInterrupted() && !shutdown) {
        clientSocket = serverSocket.accept();
        // ... start slave job
      }
    }
    catch (Exception e) {
     ....
    }
  }

  private void electNewLeader() {
    final NavigableSet<SequentialZkNode> nodes = ZkUtils.getNodes("/echo", zkClient);

    if (!zkClient.exists(zkLeaderNode.getPath())) {
      // My Leader does not exist, find the next leader above
      zkLeaderNode = ZkUtils.findLeaderOfNode(nodes, zkNode);
      zkClient.subscribeDataChanges(zkLeaderNode.getPath(), this);
      zkClient.subscribeStateChanges(this);
    }

    // If I am the leader then start
    if (zkNode.getSequence().equals(nodes.first().getSequence())) {
      LOG.info("Server on port:" + port + "  will now be notified to assume leadership");
      synchronized (mutex) {
        start.set(true);
        mutex.notify();
      }
    }
  }
  .....

  @Override
  public void handleDataDeleted(String dataPath) throws Exception {
    if (dataPath.equals(zkLeaderNode.getPath())) {
      // Leader gone away
      LOG.info("Recieved a notification that Leader on path:" + dataPath
        + " has gone away..electing new leader");
      electNewLeader();
    }
  }
}

The Echo Client is shown below which connects to the leader of the Echo Server ensemble:
public class EchoClient implements IZkDataListener, IZkStateListener, IZkChildListener {
  private Connection connection;
  private Object mutex = new Object();
  private final ZkClient zkClient;
  private SequentialZkNode connectedToNode;

  public EchoClient(int zkPort) {
    this.zkClient = new ZkClient("localhost:" + zkPort);
  }

  private Connection getConnection() throws UnknownHostException, IOException, InterruptedException {
    synchronized (mutex) {
      if (connection != null) {
        return connection;
      }

      NavigableSet<SequentialZkNode> nodes = null;
      
      // Check to see if there an Echo server exists, if not listen on /echo for 
      // a Server to become available 
      while ((nodes = ZkUtils.getNodes("/echo", zkClient)).size() == 0) {
        LOG.info("No echo service nodes ...waiting...");
        zkClient.subscribeChildChanges("/echo", this);
        mutex.wait();
      }

      // Get the leader and connect
      connectedToNode = nodes.first();
      Integer port = zkClient.readData(connectedToNode.getPath());
      connection = new Connection(new Socket("localhost", port));
      
      // Subscribe to Server changes
      zkClient.subscribeDataChanges(connectedToNode.getPath(), this);
      zkClient.subscribeStateChanges(this);
    }

    return connection;
  }

  public String echo(String command) throws InterruptedException {
    while (true) {
      try {
        return getConnection().send(command);
      }
      catch (InterruptedException e) {
        throw e;
      }
      catch (Exception e) {
        synchronized (mutex) {
          if (connection != null) {
            connection.close();
            connection = null;
          }
        }
      }
    }
  }

  private static class Connection { 
    // Code that connects and sends data to Echo Server
    public String send(String message) {
      ....
    }
  }

  @Override
  public void handleDataDeleted(String dataPath) throws Exception {
    synchronized (mutex) {
      if (dataPath.equals(connectedToNode.getPath())) {
        LOG.info("Client Received notification that Server has died..notifying to re-connect");
        if (connection != null) {
          connection.close();
        }
        if (connectedToNode != null) {
          connectedToNode = null;
        }
      }
      mutex.notify();
    }
  }

  @Override
  public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
    synchronized (mutex) {
      LOG.info("Got a notification about a Service coming up...notifying client");
      mutex.notify();
    }
  }
}

A simple test of the example starts an EchoClient and two servers. One of the servers assumes leadership and starts servicing request while the other server sits waiting to assume leadership. The client in turn sends messages which is serviced by the leader. When the leader terminates, messages are then serviced by the successor that assumes leadership.
  @Test
  public void simpleLeadership() throws InterruptedException {

    EchoClient client = new EchoClient(ZK_PORT);
    EchoServer serverA = new EchoServer(5555, ZK_PORT);
    EchoServer serverB = new EchoServer(5556, ZK_PORT);

    serverA.start();
    serverB.start();
 
    // Send messages
    for (int i = 0; i < 10; i++) {
      System.out.println("Client Sending:Hello-" + i);
      System.out.println(client.echo("Hello-" + i));
    }
    
    if (serverA.isLeader()) {
      serverA.shutdown();
    } else {
      serverB.shutdown();
    }
 
    for (int i = 0; i < 10; i++) {
      System.out.println("Client Sending:Hello-" + i);
      System.out.println(client.echo("Hello-" + i));
    }

    serverA.shutdown();
    serverB.shutdown();
  }
On running the test, you can see output similar to:
20:18:49 INFO - com.welflex.zookeeper.EchoClient.getConnection(44) | No echo service nodes ...waiting...
20:18:49 INFO - com.welflex.zookeeper.EchoClient.handleChildChange(171) | Got a notification about a Service coming up...notifying client
20:18:49 INFO - com.welflex.zookeeper.EchoServer.run(85) | Server on Port:5556 is now the Leader. Starting to accept connections...
Client Sending:Hello-0
Echo:Hello-0
Client Sending:Hello-1
Echo:Hello-1
.....
20:18:49 INFO - com.welflex.zookeeper.EchoServer.run(122) | Server on Port:5556 has been shutdown
20:18:49 INFO - com.welflex.zookeeper.EchoClient.getConnection(44) | No echo service nodes ...waiting...
Server has died..notifying to re-connect
20:18:49 INFO - com.welflex.zookeeper.EchoClient.getConnection(44) | No echo service nodes ...waiting...
20:18:49 INFO - com.welflex.zookeeper.EchoClient.handleChildChange(171) | Got a notification about a Service coming up...notifying client
20:18:49 INFO - com.welflex.zookeeper.EchoServer.run(85) | Server on Port:5555 is now the Leader. Starting to accept connections...
20:18:49 INFO - com.welflex.zookeeper.EchoClient.handleChildChange(171) | Got a notification about a Service coming up...notifying client
....
Echo:Hello-7
Client Sending:Hello-8
Echo:Hello-8
Client Sending:Hello-9
Echo:Hello-9
....

2. Rendezvous/Barrier Example: 

Distributed systems can use the concept of a barrier to block the processing of a certain task until other members of the system ensemble are available after which all the systems participating can proceed with their tasks. Having a little fun here :-) with a fictional case where Double O agents of MI-6 meet to present their reports, and reports are not edited here if you know what I mean ;-). Agents join the meeting but cannot start presenting until all the expected agents join the meeting after which they are free to present in parallel (agents are designed to grasp from multiple presenters; after all the 007 variety are trained at such things). Agents can present but cannot leave the briefing until all presenters have completed their presentation. The agent upon start up creates a ZNode under the meeting identifier, say, "/M-debrief", and then waits for all other agents to join before beginning their presentation, i.e., barrier entry. After each presentation, the agent removes themselves from the list of ZNodes and then waits for other agents to do the same before leaving the briefing, i.e., barrier exit. With that said, the Agent code looks like:
public class Agent extends Thread implements IZkChildListener {
  // Number of agents total
  private final int agentCount;

  private final String agentNumber;

  private final Object mutex = new Object();

  private final Random random = new Random();

  private SequentialZkNode agentRegistration;
  
  private final String meetingId;

  public Agent(String agentNumber, String meetingId, int agentCount, int zkPort) {
    this.agentNumber = agentNumber;
    this.meetingId = meetingId;
    this.agentCount = agentCount;
    this.zkClient = new ZkClient("localhost:" + zkPort);
    zkClient.subscribeChildChanges(meetingId, this);
  }

  private void joinBriefing() throws InterruptedException {
    Thread.sleep(random.nextInt(1000));
    agentRegistration = ZkUtils.createEpheremalNode(meetingId, agentNumber, zkClient);
    LOG.info("Agent:" + agentNumber + " joined Briefing:" + meetingId);
    
    // Wait for all other agents to join the meeting
    while (true) {
      synchronized (mutex) {
        List<String> list = zkClient.getChildren(meetingId);

        if (list.size() < agentCount) {
          LOG.info("Agent:" + agentNumber + " waiting for other agents to join before presenting report...");
          mutex.wait();
        }
        else {
          break;
        }
      }
    }
  }

  private void presentReport() throws InterruptedException {
    LOG.info("Agent:" + agentNumber + " presenting report...");
    Thread.sleep(random.nextInt(1000));
    LOG.info("Agent:" + agentNumber + " completed report...");

    // Completion of a report is identified by deleting their ZNode
    zkClient.delete(agentRegistration.getPath());
  }

  private void leaveBriefing() throws InterruptedException {

    // Wait for all agents to complete
    while (true) {
      synchronized (mutex) {
        List<String> list = zkClient.getChildren(meetingId);
        if (list.size() > 0) {
          LOG.info("Agent:" + agentNumber
            + " waiting for other agents to complete their briefings...");
          mutex.wait();
        }
        else {
          break;
        }
      }
    }
    LOG.info("Agent:" + agentNumber + " left briefing");
  }

  @Override
  public void run() {
    joinBriefing();
    presentReport();
    leaveBriefing();
  }

  @Override
  public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
    synchronized (mutex) {
      mutex.notifyAll();
    }
  }
}
Running the test, one would see something like the following where agents join the meeting, wait for the others before presenting, present at the meeting and then leave after everyone completes. Note that output is edited in the interest of real estate:
21:02:17 INFO - com.welflex.zookeeper.Agent.joinBriefing(38) | Agent:003 joined Briefing:/M-debrief
21:02:17 INFO - com.welflex.zookeeper.Agent.joinBriefing(45) | Agent:003 waiting for other agents to join before presenting report...
21:02:17 INFO - com.welflex.zookeeper.Agent.joinBriefing(38) | Agent:005 joined Briefing:/M-debrief
21:02:17 INFO - com.welflex.zookeeper.Agent.joinBriefing(45) | Agent:005 waiting for other agents to join before 
.....
:17 INFO - com.welflex.zookeeper.Agent.joinBriefing(45) | Agent:005 waiting for other agents to join before presenting report...
......
21:02:17 INFO - com.welflex.zookeeper.Agent.joinBriefing(45) | Agent:006 waiting for other agents to join before presenting report...
21:02:18 INFO - com.welflex.zookeeper.Agent.joinBriefing(38) | Agent:007 joined Briefing:/M-debrief
21:02:18 INFO - com.welflex.zookeeper.Agent.joinBriefing(45) | Agent:007 waiting for other agents to join before presenting report...
21:02:18 INFO - com.welflex.zookeeper.Agent.presentReport(57) | Agent:002 presenting report...
21:02:18 INFO - com.welflex.zookeeper.Agent.presentReport(57) | Agent:005 presenting report...
21:02:18 INFO - com.welflex.zookeeper.Agent.presentReport(57) | Agent:007 presenting report...
21:02:18 INFO - com.welflex.zookeeper.Agent.presentReport(57) | Agent:003 presenting report...
21:02:18 INFO - com.welflex.zookeeper.Agent.presentReport(57) | Agent:001 presenting report...
....
21:02:18 INFO - com.welflex.zookeeper.Agent.leaveBriefing(69) | Agent:002 waiting for other agents to complete their briefings...
21:02:18 INFO - com.welflex.zookeeper.Agent.leaveBriefing(69) | Agent:002 waiting for other agents to complete their briefings...
21:02:18 INFO - com.welflex.zookeeper.Agent.presentReport(59) | Agent:000 completed report...
21:02:18 INFO - com.welflex.zookeeper.Agent.leaveBriefing(69) | Agent:000 waiting for other agents to complete their briefings...
21:02:18 INFO - com.welflex.zookeeper.Agent.leaveBriefing(69) | Agent:002 waiting for other agents to complete their briefings...
21:02:18 INFO - com.welflex.zookeeper.Agent.leaveBriefing(69) | Agent:000 waiting for other agents to complete their briefings...
21:02:18 INFO - com.welflex.zookeeper.Agent.presentReport(59) | Agent:007 completed report...
21:02:18 INFO - com.welflex.zookeeper.Agent.leaveBriefing(69) | Agent:007 waiting for other agents to complete their briefings...
....
21:02:19 INFO - com.welflex.zookeeper.Agent.leaveBriefing(78) | Agent:007 left briefing
21:02:19 INFO - com.welflex.zookeeper.Agent.leaveBriefing(78) | Agent:003 left briefing
21:02:19 INFO - com.welflex.zookeeper.Agent.leaveBriefing(78) | Agent:002 left briefing
...
21:02:19 INFO - com.welflex.zookeeper.Agent.leaveBriefing(78) | Agent:000 left briefing

Running the code:

Download a maven example of the above code from HERE. Execute a "mvn test" to see the example in action or import into eclipse to dissect the code. The example itself runs its tests on a single ZooKeeper server. There is no reason why the same cannot be expanded to try on a larger ZooKeeper ensemble.

Conclusion and Credits:

The examples shown are highly influenced by the examples provided at the ZooKeeper site. The code does not use the ZooKeeper code directly but instead uses a wrapper around the same, i.e., ZkClient, which provides a much easier experience to using ZooKeeper than the default ZooKeeper API. The examples also rely heavily on the excellent article and supporting code by Erez Mazor who utilizes Spring Framework very nicely to demonstrate Leader Election and control of the same. I simply loved his code and images and have used parts of the same in the above demonstration. I am sure I have only touched the surface of  ZooKeeper and am hoping I can learn more about the same. If my understanding about any of the concepts mentioned above is flawed, I would love to hear about the same. Again, a very Happy 2012! Keep the faith, the world won't end on December 21'st.