SpringMVC with Netty

I’m using Spring/Hibernate to provide the Hypersocket REST API on a Netty based HTTP server. Why? well Hypersocket’s main function is a tunnelling server so the first priority is a high performance socket framework. The user interface implementation had to come second to this requirement; I certainly did not want to burden the server with an overweight server-side UI framework so I was looking for something that was lightweight. I also wanted support for Spring/Hibernate since it makes creating my domain model a breeze. So a Javascript based UI accessing REST services provided by SpringMVC controllers sounded ideal.

The problem I faced is that SpringMVC is run in a servlet container and there is no servlet implementation for Netty because the servlet API relies on the standard IO model of using InputStream/OutputStream. I decided to try and implement a lightweight servlet container for Netty so that I could plugin the Spring servlet. Here is a run down of how I managed to get this working.

I created implementations of the following servlet container interfaces. I’ll be posting a fully working example soon so I won’t go into the actual implementations here.

ServletConfig
ServletContext
HttpServletRequest
HttpServletResponse
HttpSession

Now I could start configuring my Spring environment so my domain objects are created in the usual way with a Spring ApplicationContext. Loading any application context files I’ve placed in the classpath:

ApplicationContext applicationContext = 
          new ClassPathXmlApplicationContext(
                 "classpath*:/META-INF/applicationContext.xml");

I had to code the configuration of the SpringMVC context because I don’t have a complete servlet container to configure from a web.xml file. I’ve literally just implemented the basic servlet API that will get the servlet working. So I created a AnnotationConfigWebApplicationContext (as I’m exclusively using annotations) and set my main ApplicationContext as parent:

AnnotationConfigWebApplicationContext webappContext
         = new AnnotationConfigWebApplicationContext();

// Use my main ApplicationContext as parent so it can discover my domain entities.
webappContext.setParent(applicationContext);

Next I register a DelegatingWebMvcConfiguration because I want to add a custom intercept handler for an annotation I will be creating. This will look for @Components that extend the WebMvcConfigurer interface. Even if you don’t want to add your own interceptors you should add this although you can use WebMvcConfigurationSupport instead.

webappContext.register(DelegatingWebMvcConfiguration.class);

Now setup the packages to scan for @Controller annotations:

webappContext.scan("com.hypersocket.example.web.**");

We can now setup our ServletConfig on the AnnotationConfigWebApplicationContext:

servletConfig = new HypersocketServletConfig("default", "/hypersocket");

// Set the servlet config on our AnnotationConfigWebApplicationContext
webappContext.setServletConfig(servletConfig);

Finally we can create the Spring DispatcherServlet:

dispatcherServlet = new DispatcherServlet(webappContext);

dispatcherServlet.init(servletConfig);

And there we have it, a configured DispatcherServlet that is ready to accept requests. The only thing left for us to do is to translate HTTP requests/responses from Netty into HttpServletRequest/HttpServletResponse. Here is my ChannelPipeline which uses Netty’s built-in HTTP encoder/decoder:

public ChannelPipeline getPipeline() throws Exception {
        // Create a default pipeline implementation.
        ChannelPipeline pipeline = pipeline();
        pipeline.addLast("decoder", new HttpRequestDecoder());
        pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
        pipeline.addLast("encoder", new HttpResponseEncoder());
        pipeline.addLast("handler", new HttpRequestDispatcherHandler(server));
        return pipeline;
}

This means when my HttpRequestDispatcherHandler receives a HTTP request all it has do is to translate this into a HttpServletRequest and pass this into the DispatcherServlet along with a HttpServletResponse. Upon return I then translate this back into Netty’s HttpResponse and the request is complete.

There are a number of improvements I could make, one would be to have Netty decode directly into a HttpServletRequest but that would tie the server to the servlet API and might not be appropriate for the tunneling services I’m adding but it may be appropriate for you. Another is the HttpSession support, presently its just a simple factory and some work is needed to ensure sessions are cleaned up after expiry.

I’ve only tested SpringMVC with @Controller classes that are sending/receiving entity objects with the @RequestBody, @ResponseBody annotations. I’ve not tried to use any other feature of SpringMVC so would welcome feedback if others are able to go further.

Prettify plugin issues

I’ve been trying to use the Sunburst Code Prettify plugin but it simply doesn’t render quotes in code correctly….

[prettify class=”java”]String test = “12345657890”;[/prettify]

Eventually i’ve answered my own question… It appears you have to wrap the prettify short code tags in <code> tags. This was not apparent from the installation or documentation of the plugin.

[prettify class="java"]String test = "12345657890";[/prettify]

This example is using Prettify for WordPress plugin.. Just wrap the code snippet in <pre class=”prettyprint”> tag. I’ve decided to go with this one.

String test = "1234567890";

jQuery multiple dialog problem solved

I’ve been creating a dynamic jQuery user interface for Hypersocket and came across a problem with the jQuery dialog. My user interface has a core that dynamically loads ‘modules’ from the menu. This will allow us to plugin new functionality in the future without hard coding menu options. The basic function is for each menu option a html fragment is loaded into a div.

When a user clicks on a new menu option I empty the main content div:

$('#mainContent').empty();

Then load the new modules content:

$('#mainContent').load('modules/content' + name + '.html', function() {
    hideBusy();	
});

The problem I had is that when the page fragment is loaded it was creating a dialog with one of the divs in the fragment, nothing unusual except that JQuery was placing this dialog element in the body of the DOM. This meant it was moved outside of my main content div, so subsequent loads of the modules content would see additional dialog divs being created in the document. This caused problems with my dialogs as some select tags that were loaded based on their id would see multiple versions of the data.

I found the solution here. Simply move the dialog back into the main content div once it has been created.

$('#addRealmForm').dialog({ .. });
$('#addRealmForm').parent().appendTo('#mainContent');

This way when my main content div is emptied, the dialog is removed too. There is only one problem with this, the dialog is constrained to the parent div so if you drag it around the browser it will disappear when its bounds go outside the parent.

This can be resolved with a little more code before we open the dialog:

$('#addRealmForm').parent().appendTo('body');

And when we close the dialog we put it back where we want it in the main div:

$('#addRealmForm').parent().appendTo('#mainContent');

Dropping GWT for jQuery

I’ve been playing around with GWT for a few days and have come to the conclusion its too bloated for my needs. I want Hypersocket to be as lightweight as possible and the GWT UI just doesn’t feel right. I would also have to get over the issues of not being able to run server-side code within GWT itself (because Netty is providing the HTTP layer) and was looking at having to proxy my REST API calls during development.

Using JQuery makes things simpler, and I can get rid of that GWT Eclipse plugin that seems to have slowed down my development environment since it as installed.