I started working on this “yet-another-web-server” project for one of the most important reasons: because its fun. I got inspired for doing this after reading about the Netty framework and all the positive reviews that people write.
My requirements for this server are
- provide a minimal MVC framework that uses renderSnake to render HTML pages
- (distributed) Http session management using JBOSS Infinispan, a modern caching solution
- use Netty , a well-designed fast server framework which I will use for its HTTP support
- components are wired together using Guice, a lean dependency injection library
- support for a minimal feature set to run Web applications
- GET, POST
- Redirects,Forwards
- Sessions, Cookies
- Error Handling (404,500,...)
- Logging using SLF4j
- Basic static content serving
To "eat my own dogfood", I re-implemented the renderSnake website (which is just a Java application) using the renderShark engine.
The project is hosted on googlecode. Have a look at the example project that demonstrates all the features.
For the past month, I have been working on a new iPad Web application that recently was launched at 6hoek.com.
This application provides easy access to the complete product catalog of the Dutch online webshop bol.com.
Because it is targeted to owners of tablet devices such as the Apple iPad, I decided to embrace the upcoming JQuery Mobile framework (JQM), an open-source Javascript library that provides an unified UI to various mobile devices. For producing the HTML markup, I (obviously) choose renderSnake, an open-source HTML component library that promotes writing UI components in Java instead of templates.
rendersnake is a Java library for creating components and pages that produce HTML using only Java. Its purpose is to support the creation of Web applications that are better maintainable, allows for easier reuse, have testable UI components and produces compact HTML in an efficient way.
This blog post explains how to start from a carefully designed rich HTML page and create new or use the components available in the library.
renderSnake is a open-source library for creating components that produce HTML using only Java. By defining Java classes for HTML components and pages you can exploit all the language features (e.g. inheritance, composition, type-checking) and IDE tooling (e.g. refactoring, unit-testing, references search, debugging,…). In addition, renderSnake is designed to produce compact HTML in an memory efficient way.
The "V" in MVC
Basically, renderSnake is responsible for the presentation layer of a Web application. It has no dependencies with an application framework but it does provide classes to integrate with other technologies such as JavaServer Pages and Spring-MVC. Spring-MVC is a popular implementation of the MVC architecture. This pattern isolates "domain logic" (the application logic for the user) from the user interface (input and presentation), permitting independent development, testing and maintenance of each (separation of concerns).
Example
Below is an example of a Spring-MVC based setup of components. ProductListController is a component that is responsible to handling incoming requests. That execution starts by retrieving the Product objects (Model) through a Product Data Access Object. Then a ProductListPage object is created and asked to render itself. Each UI component that is part of the ProductListPage is asked to do the same. The response will have the resulting HTML content.
- missing image /2011/02/spring-mvc-rendersnake.png
Controller
The method below is part of the ProductListController and is called with a prepared HtmlCanvas object that captures the request,response and output writer. Before rendering the page using the HtmlCanvas, all required domain objects are retrieved and made available to the PageContext (Map) of the HtmlCanvas object. Now the HtmlCanvas has all the information needed to perform the rendering phase.
@RequestMapping("/productlist.html")
@ResponseBody
public void showProductListPage(HtmlCanvas html) throws IOException {
html.getPageContext().set("products", this.productListDao.getBestSellersProductList());
html.render(new WebshopLayoutWrapper(new ProductListPage())));
}
View
Using renderSnake, the View layer is implemented by a collection of small, potentially reusable, UI component classes that are composed into Page objects that represent HTML content.
Class Head is an example UI component responsible for rendering the head section of every HTML page. It implements the Renderable interface and uses the HtmlCanvas parameter object for rendering. The HtmlCanvas object has methods of all elements (tags) in order to write HTML content. Using the HtmlAttributesFactory, you can specify the attributes for each HTML tag. By convention, the method source has a format that uses indentation to see the nesting of tags. This is not required but improves its readability.
JNIPort for VisualWorks provides a way to use Java and its huge number of available libraries directly from Smalltalk.
For example, to access the Google Spreadsheets APIs and Tools, you need to download the Java client libraries and all its dependencies. The paths to there Jars must be known to the JVM and can be set through JNIPort. For easy deployment, I put together a single jar using an Ant build script such that the Runtime settings could be:
SelfDianogse is a library of tasks to diagnose a running system with respect to its dependent external resources. Recently, I did some Rails development and was thinking about how to implement it for the Ruby on Rails framework ? Obvious choice is to make a plugin that on installation adds the SelfDiagnoseController.rb to the application. Because of the scripting nature of Rails framework, putting the configuration in XML (as it is done for Java) is not the Ruby-way. So either use YAML or put the configuration directly into the controller. Let’s investigate the latter.
In the upcoming release 1.1 of the SelfDiagnose task library, a new task has been added called CheckEndecaService. Endeca is commercial software that provides excellent Search services to e.g. e-commerce web applications. This particular task checks the availability of that service and can perform a simple query. To implement this, the following snippet has been used:
HttpENEConnection connection = new HttpENEConnection();
connection.setHostname(host);
connection.setPort(port);
UrlENEQuery eneQuery = new UrlENEQuery("N=0", "UTF-8");
ENEQueryResults eneResults = connection.query(eneQuery);
Navigation navigation = eneResults.getNavigation();
long numERecs = navigation.getTotalNumERecs();
double time = eneResults.getTotalNetworkAndComputeTime();
Without a full understanding, you can see that this snippet is using classes which belong to the Endeca API package. SelfDiagnose is a open-source library and therefore can and will not have any dependencies on commerical software. So how can we still use this code without the compile time dependencies?. Of course, in order to execute this code, the runtime dependencies must be available. It does not make sense to use the CheckEndecaService if your application is not using it.