Tag Archives: spring

A Note on Helpers

In my previous post on Spring and ExtJS, you might have noticed the usage of a class called ExtData in the methods of the ContactController. I didn’t explain it at the time, but want to clarify what it is and why I created it.

There is a lot of boilerplate code involved in sending a response back to a request from ExtJS. You’re always going to return a Map, which has a success property, and possibly data, total and message properties. A typical response would look like this:

This gets annoying after you’ve done it a couple dozen times in the same application, so like every good (lazy) programmer, I implemented a simple class to deal with this. Take a look at the ExtResponse and ExtData classes in the org.sporcic.extjs package.

ExtResponse is the base class that simply deals with the success and message properties. The message property is only serialized if if is not null, thanks to this Jackson JSON attribute:

The ExtData class extends this class and knows how to deal with the data and total properties. It provides a simple method to add data to an internal list and correctly calculate the total property. This simplifies the controller methods to look like this:

Technically, I only removed one like of code from the previous example, but using the ExtData abstraction makes the code easier to read and eliminates tracking down a hard-to-find error in case you mis-type the name of one of the properties.

More ExtJS and Spring

It has been a while since I wrote my previous post which outlined a sample application using ExtJS and Spring. Since then, we’ve seen a new major version of both frameworks released, with ExtJS up to v3.3 and Spring sitting at 3.0.5.

ExtJS added a lot of cool features on the path to 3.3, but the most significant amount of cool stuff happened with the release of Spring 3.0. This release of Spring made it significantly easier to use JSON and REST, which eliminated a lot of the hackery that I had to do in my template with Spring 2.5.

I’ve been working on an updated version of my template, which makes use of all these new features, and decided to present it as a work-in-progress. The first part I want to talk about is how to get an Ext.data.JsonStore talking to a Spring MVC controller for CRUD operations. Loiane Groner wrote a pretty nice post on getting this wired in with an EditGrid, but it missed some of the real coolness with Spring 3.0.

I’ve pushed my sample application to GitHub to make it easier to get the big picture. The sample is a very simple webapp which uses a single domain object called Contact. The full project includes the Maven POM file along with a whole project which uses an HSQLDB with a full MVC stack in Spring. I’m going to ignore everything below the controller for this tutorial, but you can check out the rest in the full project.

Let’s start simple by demonstrating the GET operation, which will retrieve a list of all the contacts we have in our repository. Here is the application snippet from ContactController. Note, I’m using images so I can easily highlight sections. You can grab the raw source from the GitHub link above.

So the easy stuff first. I’ve annotated the ContactsController class with the @Controller stereotype from Spring to enable auto discovery. The @RequestMapping attribute says that this controller with catch all requests for ‘/contacts’. The getContacts() method is setup to catch any HTTP GET request, thanks the @RequestMapping annotation on the method itself. Finally, the real magic happens with the @ResponseBody annotation on the method return value.

@ResponseBody tells Spring it should not try to find a view and should just encode whatever object you are returning and send it back to the browser. Since we’re going to make an XMLHttpRequest from the browser, Spring will automagically encode the response in JSON format. The only caveat is that the Jackson JSON processer must be on the classpath, which my Maven POM file takes care of.

On the client side, the App.js file defines the Ext.data.Record, Ext.data.Reader, Ext.data.Proxy and Ext.data.Store. For simple applications, it is usually overkill to declare them like this, but I’m explicitly defining them to show how they will integrate with the Writer for updates.

For the Proxy, I’m setting restful to true, which means it will use the HTTP verbs GET, POST, PUT and DELETE for the CRUD operations. The url is set to send all those to the our controller above.

To make things interesting, I include a date field in the definition of the Record. This is used to show off one of the cool features of Jackson JSON and how it handles serialization.

Finally, I create the Store with the Proxy and Reader. I set autoSave to false, so I can manually force saves and loads from the console in Chrome.

In the current state, I haven’t wired in any widgets, so I’ll use the console to exercise the store. If you run the WAR file after generating it with Maven (mvn package), you can open up the JavaScript console in Chrome when you’re on the main page. Here’s how the store is loaded:

After executing the load() method of the store, you can see it loaded 10 items. If you enabled resource tracking, you can see the actual request looked like this:

The response is a JSON string that looks like

This is the typical response an Ext.data.Reader is looking for. Notice that the dates are correctly formatted as YYYY-MM-DD. This is handled via a custom attribute on the Contact domain object:

The method itself returns a Date. Without the @JsonSerialize attribute, this property would be serialized in the JSON response by calling its toString() method, which is not a desirable outcome. The ExtDateSerializer class does custom serialization of the Date object to convert it to a String using a DateFormat. The @JsonProperty annotation configures what name the property should have when serialized to a JSON object. Without this annotation, the property would have the name birthDate. I’m overriding that, specifying it should be called dob when serialized.

Now lets try to go the other direction and write (POST) a new Record from our Ext.data.Store to the ContactsController. Here is the (incorrect) Writer. We’ll get to that “incorrect” part in a minute, but first the easy stuff:

You must set encode to false, or else the Writer will try to send the payload as HTTP form data, not JSON. The error you get looks like this if you don’t set encode to false:

Note the HTTP error code is 415. Every other error you get will be a 500. It is only if you don’t set encode to false that you’ll get a 415.

Next we set writeAllFields to true. If you don’t do this, only the properties that have changed for a Record will be transmitted. We want everything server side for deserialization, so this ensures the whole object shows up at the server.

Finally, I set listful to true. This is hugely important for getting JSON deserialization to work correctly in the controller. This option says to wrap all updates inside a JSON array, even if there is only a single Record being sent. Since you can’t overload controller methods in Spring MVC controllers, we need to be able to catch both single and multi-record updates with a single method. Setting the writer to listful ensures that happens.

The controller method catching our new Record looks likes this:

The @RequestMapping annotation says that this method will catch all POST requests to the /contacts URL. The @RequestBody is new in Spring 3 and is the incoming analog to @ResponseBody. It basically tells Spring to attempt to deserialize the incoming payload into a Java object, in this case an array of Contacts. The deserialization is determined by the request headers. In this case, Spring will see it is JSON and will automagically use Jackson JSON to try and deserialize the payload to the correct object type.

Note that I return a list of Contact objects. ExtJS is expecting the return value to be a list of the same objects, post-save, with the id property set. It assumes these are in the same order that was sent, so do not shuffle the order around.

Setting listful to true in the Writer is what allows us to configure this method to accept an array of Contact objects. Even if there is only one Record coming from the Ext.data.Writer, it will be wrapped in a JSON array and deserialized into an array of Contact objects.

Now what about the birthdate property? Again, I use a Jackson JSON annotation to configure what field gets read (“dob” in this case), and how that field gets turned back in to a java.util.Date instance.

My ExtDateDeserializer class does the opposite of the ExtDateSerializer class. It uses a DateFormat to parse the string in the JSON property for dob back into a java.util.Date.

So lets try to create a new Contact and save it. Here’s the console output:

This is where we get to that “incorrect” thingy I mentioned above. The default Writer will attempt to serialize this save() request like this:

So the Writer is sending a JSON object, which contains a property called “data” which contains the array of new App.Contact records we recreated. The problem is that Spring and Jackson are looking for a simple JSON array that contains the new App.Contact records. So we need to customize the Writer to make this work right. Here is the custom Writer implementation:

I override the render method of the default Writer to directly output the JSON array of Records, and not put the wrapper object around it. Using this SpringWriter instead of the default Writer results in a payload like this:

Notice there is no longer the wrapper. When we run the console code again, we get a successful save:

So that covers reading the list of Contacts and adding a new Contact. Again, the code is available on GitHub so you can dig in to it. I’ll follow-up with another post on the PUT (update) and DELETE methods, along with wiring this in to some widgets.

Springing Around with ExtJS

NOTE: I have an update to this article which talks about Spring 3 with ExtJS 3.

While playing around more with ExtJS and Spring, I ran in to one of my favorite annoyances — setting up a new project. I can create a new webapp in IDEA (or Eclipse) and add some dependencies, but it is still pretty empty. Maven can go a bit farther, but I don’t like how it handles transitive dependencies. None of these will really give me a good starting point out of the box without either copying a bunch of stuff over from other projects or writing a lot from scratch.

To finally scratch that itch, and move further along the Spring & ExtJS path, I turned my demo project into a basic template. The zip archive that you can grab at the bottom is a fully-configured Spring web application, including Tiles, Spring Security, Spring MVC, custom JSON view, Transactions and a Datasource.

To get started, grab the file, extract it to some directory. Open a shell, navigate to the Template directory and run the ant command ant dist. This will compile the whole project and create a Template.war file in the dist directory. Note, I use Java 6 for all development, so if you’re not at least at Java 5, you won’t be able to use this.

Before you drop the war file into Tomcat’s webapp directory, you’ll need to setup the database. First, copy the jar files in lib/tomcat into Tomcat’s lib directory. This is the MySQL JDBC driver and the JTA files for transactions. You’ll then need to create a new database on your local MySQL instance called tomcat. For simplicity in development, create a user with all rights to the tomcat database. Here’s the code to run from a MySQL shell:

create database tomcat;
use tomcat;
grant all on tomcat.* to tomcat@localhost identified by 'apache';

Your other option is to just put in your MySQL root username and password. To do that, or change the connection string completely, edit context.xml under web/META-INF. If you don’t use MySQL, you will have to edit this file and also put the correct driver in Tomcat’s lib directory.

Once you have the database setup, drop the Template.war file into your Tomcat webapps directory and startup Tomcat. Assuming Tomcat is configured to listen on port 8080, you can open the sample by browsing to http://localhost:8080/Template

The application only has a couple pages. First, the login page:

Login Page

Spring Security is configured to route unauthenticated requests through this page for login. You can take a look at the applicationContext-security.xml file in WEB-INF to see how this was done. There are two users configured for now. User scott with a password of tiger and user bob with a password of password. Yes, not very clever, but it works. Scott is in both the ROLE_ADMIN and ROLE_USER roles, while Bob is only in ROLE_USER.

If you login with scott, you’ll be taken to the index page, which looks like this:

Home Page

The index page simply contains a text box with a button. Entering a message and pressing the button results in an Ajax call to the server which echos the message back to the page. An HTML element in the middle of the page is updated with the result via JavaScript.

You’ll notice in the footer of the page you can see the currently logged in user on the left, and a link to log out on the right. Clicking the log out link takes you to the logout page, which looks like this:

Logout Page

Again, nothing fancy. Just a message saying you have logged out and a link to login again. Use the login link to login as bob and try the echo functionality again. This time you get a different result:

Not an Admin

This demonstrates what happens with Spring Security via annotations. Here’s the echo method in the service layer:

As you can see, the method is secured with an annotation indicating the user must be in the ROLE_ADMIN role to use the method. Bob is only in the ROLE_USER role, so the call to this service fails.

The application makes use of a ResourceBundleMessageSource for the pages mapped through the htmlDispatch servlet. The login.jsp and logout.jsp don’t go through the dispatch servlet, so they can’t use the message bundle for the window and page title.

There is way too much to this simple application to cover completely now, but I’ll give the highlights of what to go look at in the major configuration files. Paths are relative to the project root:

  1. web/WEB-INF/web.xml – notice that I configure two dispatch servlets. One catching *.htm and one *.json. This sets things up to treat Ajax requests differently. Spring Security is also configured here.
  2. web/WEB-INF/applicationContext.xml – typical application context for a Spring application. I turn on annotation handling with package scanning under the sample.core package. Apache Tiles is configured in this file, and I have also configured a Transaction Manager around the JDBC DataSource. You should tweak this based on your underlying persistence preferences. I’m a RowMapper fan, but you can plug in Hibernate or JPA.
  3. web/WEB-INF/htmlDispatch-servlet.xml – the context for web (*.htm) requests. This sets up the ResourceBundle for messages and a typical ViewResolver mapping the *.htm requests to jsp files under web/WEB-INF/jsp. Also configures component scanning for the sample.web package.
  4. web/WEB-INF/jsonDispatch-servlet.xml – the context for Ajax (*.json) requests. Configures component scanning for the sample.json package and specifies a custom Ajax ViewResolver. This will automagically serialize all ModelMaps returned out of the Controller responded to *.json requests to JSON.
  5. web/WEB-INF/applicationContext-security.xml – so simple to look at, yet so painful to figure out. This is the Spring Security configuration file. Although it looks deceptively simple, it was a beating to figure it all out. It enables annotation-driven security, which you saw on the EchoService above. It also sets up the form login and locks down all the pages. Note I leave the /resource directory open. This is where I put all my javascript, stylesheets and images. If you want to secure those resources, you’ll need to get more specific on the intercept-urls.
    Users are declared at the bottom. Passwords are clear text, which is fine for a trivial demo, but you would want to replace this with something more industrial-strength in a real application.
  6. web/WEB-INF/tiles-config.xml – the Apache Tiles configuration. I only setup one definition here to keep it simple.
  7. web/WEB-INF/jsp/layouts/baseLayout.jsp – the base layout used for tiles. I’m only inserting content at two locations in the template. In the HTML head section, I allow for an optional insert of headerContent. I use this to include JavaScripts specific to a page. The other content is within the center div called mainContent.
    Note that the body is pretty empty and that the divs all have the x-hidden class. This means they are not normally visible. I use an ExtJS Viewport for layout, which uses the contents of these divs.
  8. web/resources/javascripts/layout.js – this JavaScript file was included in the baseLayout.jsp above. It creates the Viewport using a border layout.
  9. web/resources/javascripts/index.js – the JavaScript file included for the index.jsp page. It decorates the plain HTML inputs on the page to do the cool Ajax stuff. Note towards the bottom how I use ExtJS to set focus on a form field and to bind the ENTER key to the submit button.
  10. web/resources/javascripts/login.js – the JavaScript file use for the login.jsp page. If you look at login.jsp, you’ll notice there is no form. Everything is created by ExtJS from the login.js file, including the cool box effect. One trick is that Spring Security wants a normal form POST for the login form. I override the form to do a standard submit instead of an Ajax submit and set the form action explicitly.

This covers the major features. I’ll be using this as a base for other projects and will be expanding out my ExtJS demo. Since there are pretty much zero examples out there of tying together this stack, I hope this can be of use to some folks.

Project Template

  • 2/28/2009 – upgrade to ExtJS 2.2.1, fixed compile issue on Linux, added in iBatis for ORM
  • 3/26/2009 – I’ve setup a dev server with the latest version of the template at CodeZombie.com so you can check it out without having to install. User scott/tiger for credentials. I’ll be updating this install with a more feature-rich demo application shortly
  • 3/28/2009 – changed around the project structure and build.xml to use Ivy for dependency management. Check the README.txt file in the root directory for the details.
  • 4/28/2009 – updated the included JSON encoder to be able to return JSON arrays by using the key _root in the model map. If this key is found, its content will be used as the root element of the return JSON instead of encoding the whole map. Also removed the unicode characters from StringScrubber to make the compiler on Linux happy.

p.s. this pulls together a lot of jars and pieces from different folks to build the demo. If you use this for more than playing around, you need to make sure you respect whatever licenses the authors have in place.

Back to Business

So I had to ditch my PHP mistress for a bit and come back to the real world. I spoke tonight at the Spring Dallas User Group, giving a presentation on the ExtJS JavaScript library and integration with Spring MVC. We had close to 20 people in attendance, which was more then I expected given the short notice.

Erik Weibust and I had discussed me presenting to the group several months ago. I orginally planned to present in July, but vacation plans got in the way of the meeting date. In the interim, quite a bit happened in the ExtJS world. The fallout from the change to GPL from LGPL had simmered down, and they released a new version.

The presentation went well. Some folks had worked with ExtJS while others were learning about it for the first time. In spite of the turmoil from the license change, I’m still very excited about it. The 2.2 release added some cool stuff and I’m looking forward to digging in to it on a project.

For those in attendance, or the simply curious, I’ve attached the presentation, sample project and my own Spring JsonView implementation. Note that for the sample project, you will need to download the ExtJS distribution yourself and place the contents of it in the web/resources/ext directory. I didn’t want to redistribute ExtJS in my sample.

ExtJS Presentation

ExtJS/Spring Demo Project

Custom JsonView Project