Search This Blog

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.