RESTful Spring MVC and ExtJs (Episode 2, The ExtJs Stuff)

In the last post we talked about configuring Spring MVC for use as a RESTful API with the intention of using ExtJs for the UI work. In this post, I’ll review the ExtJs configuration work and highlight some of the important aspects of the project. I’ve included an example interface that will work with our previously configured back end. This app will be called ‘Gizmo Manager’. It will exercise the ExtJs MVC components and their RESTful proxies. Again, all of the source for this is on Github, for you to follow along with. On with it!

Installing ExtJs
There are two flavors of ExtJs – the open source version and the commercial version. For this project, I’m using the open source version (obviously)- 4.1.1 – you’ll notice I don’t have it checked in. The download(s) are available from Sencha, and although I haven’t used it, there is a copy on the Sencha CDN here. For this example, I’ve downloaded it and dropped it into my web project’s ‘js’ folder.
ExtJs install

Configuring ExtJs
To get the foundation for our app created, we’ll want to update our index.html file to reference both the ExtJs distribution, and our app (which will soon be created). Here’s what mine looks like when I’m done:

<html>
  <head>
    <title>Gizmo Manager</title>
    <link rel="stylesheet" type="text/css" href="js/extjs/resources/css/ext-neptune-debug.css">
    <script type="text/javascript" src="js/extjs/ext-all-debug.js"></script>
    <script type="text/javascript" src="js/app.js"></script>
  </head>
  <body></body>
</html>

You’ll notice we’ve added two items related to our home page – a path to ExtJs itself (ext-all-debug.js), and a stylesheet reference. There are already-minified versions of ExtJs available in the distro, but for this example, I’m using the debug version as it is easier to troubleshoot configuration problems using it. As for the stylesheet, Neptune is one of the few themes that ExtJs comes packed with. They each have drawbacks, but I think Neptune has the most modern look and feel.

Next we’ll create our application’s folder structure. You’ll notice in the screenshot above a folder named ‘app’ and a file named ‘app.js’. These are both located in the /web/js folder, right alongside my extjs install. Our app.js file contains our application’s bootstrap information. This is how it looks:

Ext.application({
    name: 'gizmoManager',
    appFolder: 'js/app',
    controllers: ['GizmoController'],
    launch: function() {
        Ext.create('gizmoManager.view.MainViewport');
    }
});

You’ll notice some important items in this file. This is where we name our app and let ExtJs know where the source is located. We also give ExtJs a list of controllers to set up, as well as a view to create on launch. In this example, we’re using the MVC capabilities of ExtJs, so if you’re familiar with any other MVC framework, this should be easy to follow along with, at least structurally.

Our app directory has four folders in it – one each for controllers, models, views, and stores – all layers of the ExtJs flavor of MVC.
folders

Creating the Application
Let’s follow the ExtJs stack from front to back. Remember the default view we added to our app.js file? This is where our applications view components will be displayed. If we had multiple views in our app, our default view might be a card layout or a tab panel, where multiple views could be managed. In our app, we’ll configure a single view – more on that shortly. Here is our default view, the MainViewport.js, with it’s reference to our app’s single view component.

Ext.define('gizmoManager.view.MainViewport', {
    extend : 'Ext.container.Viewport',
    alias : 'widget.mainViewport',
    requires: [
        'gizmoManager.view.MainContainer'
    ],
    items : [{
        xtype : 'mainContainer'
    }]
});

In this file, you’ll notice two references to our app’s single view component – once in a parameter called ‘requires’ and once in a parameter called ‘items’. Think of items listed in the ‘requires’ parameter to ‘imported’ (in java terms) in to this file. Items in the ‘items’ parameter are displayed items, in the order they appear in the ‘items’ array.

The View
Since our ‘MainContainer’ is our application’s single view file, and our goal is exercise all of the RESTful API we created in our last post, you may think that it’s going to be very complicated. It’s really not! Adapting the gridpanel example from ExtJs docs, we’ll have an editable grid, which we can use to add, remove, update ‘Gizmos’. This file is called MainContainer.js, and is located in the root of the ‘view’ directory, along with MainViewPort.js. Our MainContainer.js file looks like this:

Ext.define('gizmoManager.view.MainContainer', {
    extend: 'Ext.tab.Panel',
    alias: 'widget.mainContainer',
    title: 'Gizmo Manager',
    items:[
        {
            xtype: 'gridpanel',
            title: 'Gizmos',
            store: 'Gizmo',
            name: 'editableGrid',
            columns: [
                {text: 'ID', dataIndex: 'id', width: 300},
                {text: 'DESCRIPTION', dataIndex: 'description', width: 300,
                    editor: {
                        xtype: 'textfield',
                        allowBlank: false
                    }}
            ],
            columnLines: true,
            selModel: 'rowmodel',
            plugins: [
                Ext.create('Ext.grid.plugin.RowEditing', {
                    clicksToEdit: 1
                })
            ],
            dockedItems: [{
                xtype: 'toolbar',
                items: [{
                    action: 'add',
                    text:'Add Something'
                },'-',{
                    action: 'remove',
                    text:'Remove Something',
                    disabled: true
                }]
            }],

            width: 600,
            height: 300
        }
    ]
});

You can see we create our grid and add columns to display Gizmo data, we have added the row editing plugin for our grid panel (more info in the ExtJs docs on those topics), and we have also added a couple of buttons to the grid’s toolbar – one to remove items and another to add them. The buttons, the grid itself, and the rest of this don’t do much without the rest of the stack.

The Controller
The controller wires the stack together, serving as the middle man between the view and store/model, just as it would in any other MVC framework. We’ll named it GizmoController.js, and put it in our ExtJs app’s ‘controller’ folder. The controller’s main function in this example is listening to view events and interacting with our store/model. Overall, this is a pretty basic example, but again, exercises our whole API.

Ext.define('gizmoManager.controller.GizmoController', {
    extend: 'Ext.app.Controller',
    stores: ['Gizmo'],
    views: ['MainContainer'],

    refs:[
        {
            ref: 'mainContainer',
            selector: 'mainContainer'
        },
        {
            ref: 'editableGrid',
            selector: 'panel > gridpanel[name=editableGrid]'
        }
    ],

    init: function () {
        this.control({
            'mainContainer > gridpanel[name=editableGrid]' : {
                edit: function(editor, object) {
                    object.store.save();
                    object.store.commitChanges();
                },
                selectionchange: function(current, selections) {
                    this.getEditableGrid().down('button[action=remove]').setDisabled(selections.length == 0);
                }
            },
            'mainContainer > gridpanel > toolbar > button[action=add]' : {
                click: function(button) {
                    this.getGizmoStore().add(Ext.create('gizmoManager.model.Gizmo'));
                }
            },
            'mainContainer > gridpanel > toolbar > button[action=remove]' : {
                click: function(button) {
                    var selection = this.getEditableGrid().getSelectionModel(),
                        me = this;
                    Ext.each(selection.selected.items, function(gizmo) {
                        me.getGizmoStore().remove(gizmo);
                    });
                    me.getGizmoStore().sync();
                }
            }
        });
        this.getGizmoStore().load();
    }
});

In the ‘init’ property of the controller, we’ll see the four methods of our API as they exist in code. For the parameter-less GET (or ‘index’ in Grails/Rails terms), we use our GizmoStore’s load method. Our controller has a reference to the GizmoStore in it’s store array. This gives us an accessor to the store for free.

this.getGizmoStore().load();

For deletions, you can see the listener on the remove button’s click method:

'mainContainer > gridpanel > toolbar > button[action=remove]' : {
                click: function(button) {
                    var selection = this.getEditableGrid().getSelectionModel(),
                        me = this;
                    Ext.each(selection.selected.items, function(gizmo) {
                        me.getGizmoStore().remove(gizmo);
                    });
                    me.getGizmoStore().sync();
                }
            }

In this case, we’re using the control block, providing a path to the element we’d like to control (in this case, the delete button), and listening for the click method there. Again, you can see accessors available here – getting the editable grid – but this one is not free. In the controller, you’ll see the ‘refs’ parameter. The refs parameter allows us to define and name an array of objects for which we’d like accessor methods. In this case, we’ve got accessor for our view, and our view’s grid. Two other important things here: you can see the call to the GizmoStore’s remove button, followed by a call to the sync method.

The Model
The model (Gizmo.js) is stored in our app’s model folder. The model is used as a value object for the data going to and coming from our API. You’ll notice this is not a fat model like an ActiveRecord or a Model in Grails.

Ext.define('gizmoManager.model.Gizmo', {
    extend: 'Ext.data.Model',
    fields: ['id','description']
});

Not much more than the field config in our example, but more complex apps include validation information, proxy references, parent/child relationship configuration and much more. You can see the names of the fields in our model match with the ‘dataIndex’ parameters of the columns in our view. This is how our model is correctly bound to the grid.

The Store
The store is a singleton and maintains the client-side cache in ExtJs MVC applications. Our store contains a configured proxy through which the calls to our API are made. There are many convenient methods on the store for dealing with data in memory – comprehensions, finders, transformers, etc. In our example app, we’ll just be using the store for it’s proxy and synchronizing immediately after changes (see controller above).

Ext.define('gizmoManager.store.Gizmo', {
    extend: 'Ext.data.Store',
    model: 'gizmoManager.model.Gizmo',
    proxy: {
        type: 'rest',
        url : 'spring/gizmos',
        reader:{
            type: 'json',
            root: 'gizmos'
        }
    }
});

Above you can see our store’s configuration. The store contains a reference to the Gizmo model and a configured proxy. You’ll notice the proxy configuration points to our API, and is of the type ‘rest’. The ‘rest’ type proxy automatically makes calls to our API when we call methods like ‘load’ and ‘save’ and our store. Much more information in the ExtJs docs on that topic in the Ext.data.proxy.Rest class.

Run!
If you’ve been following along (or just skipped to downloading the project on Github), we should be able to run the app at this point. Here is what we should see:
Gizmo Manager
Click around and delete, edit, and add new Gizmos.

I hope this helped you get going faster than I did. Next up, design patterns in Scala!

RESTful Spring MVC and ExtJs (Episode 1, The Spring Stuff)

My latest adventures have taken me to a client replacing legacy Flex apps with ExtJs apps backed by Spring. In this two part post, you’ll see the product of the many bits of documentation, examples and blog posts I had to cobble together to get this set up, in hopes that it will serve as a complete example for someone else.

Background
If I had my druthers, I’d choose something a little more lightweight for the task at hand – at one time, this was supposed to be a Grails back end, and I was looking forward to getting back in to that mix. That option vaporized and we are now taking it a little slower with a Spring back-end. Thankfully, I work with folks that can make a little lemonade of that lemon, and we’re at least working with pretty close-to-the-latest core Spring, Spring MVC, Spring Data – version 3.2.1.

At the end of this post, you’ll have a working RESTful API provided by Spring using Spring MVC, and some of it’s new features. The source code is on Github so you can follow along. I will walk through the app’s configuration as well as the particulars of the controller class that will serve the front end.

Getting Started
We’ll start with the basic project layout and required jars:

ExtJs Project Layout

<ivy-module version="2.0">
    <info organisation="com.rodenbostel" module="SpringExtJs"/>
    <dependencies>
        <dependency org="org.springframework" name="spring-aop" rev="3.2.1.RELEASE" />
        <dependency org="org.springframework" name="spring-beans" rev="3.2.1.RELEASE" />
        <dependency org="org.springframework" name="spring-core" rev="3.2.1.RELEASE" />
        <dependency org="org.springframework" name="spring-context" rev="3.2.1.RELEASE" />
        <dependency org="org.springframework" name="spring-context-support" rev="3.2.1.RELEASE" />
        <dependency org="org.springframework" name="spring-web" rev="3.2.1.RELEASE" />
        <dependency org="org.springframework" name="spring-webmvc" rev="3.2.1.RELEASE" />
        <dependency org="org.codehaus.jackson" name="jackson-core-asl" rev="1.9.12" />
        <dependency org="org.codehaus.jackson" name="jackson-mapper-asl" rev="1.9.12" />
        <dependency org="cglib" name="cglib-nodep" rev="2.2.2" />
    </dependencies>
</ivy-module>

Spring MVC Config
Spring 3.2 provides java-based Spring configuration (docs here). We’ll see a few examples of that here. The dispatcher servlet declaration and config remain in XML – all other bean declarations and config will be in java. First, in our web.xml file (/web/WEB-INF/web.xml), we need to configure the Spring MVC Dispatcher Servlet, as well as the Context Loader and it’s config locations. You can see a few important things here. The dispatcher servlet config itself, and it’s servlet mapping are near the bottom. They handle request routing, and will route requests behind “/spring/” to Spring MVC. We also see two context-params – the first (ContextClass) will tell Spring MVC to accept annotated classes as input in place of XML. The second (contextConfigLocation) will tell Spring MVC in which package to find the annotated classes that will make up the Spring config. Here is the web.xml in question:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.rodenbostel.springextjs.config</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/spring/*</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>

Next up is configuring the dispatcher servlet itself in dispatcher-servlet.xml. Not much to do here – we’re simply telling Spring MVC that we’ll be using annotations to drive our config. Note that by default, Spring MVC provides JSON request marshalling/unmarshalling using the given config (more on that later).

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven/>

</beans>

Moving On…
…to the interesting parts. We’ll start with the java based config. In this example, we’ll rely on component scanning and autowiring, and keep the config to a minimum. We’ll be scanning the ‘com.rodenbostel.springextjs’ package for more Spring Beans…

package com.rodenbostel.springextjs.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.rodenbostel.springextjs")
public class Config {
}

RESTful Controller
You can see the annotated controller below. There is quite a bit of config directly in the file, but from the start, you should notice that the class is marked with the controller interface annotation. Spring will recognize this during the context scan and make this a Spring bean. Next, we see five methods – one for each of the 4 familiar operations of CRUD, plus one that retrieves a single item for convenience sake, though still providing the same interface from the caller’s perspective. The 5 methods follow the paradigm used by scaffolded RESTful controllers created by Grails and Rails. In our app, the items the interface is being provided for are called ‘Gizmos’.

package com.rodenbostel.springextjs.controllers;

import com.rodenbostel.springextjs.viewmodel.Gizmo;
import com.rodenbostel.springextjs.viewmodel.ManyGizmoResponse;
import com.rodenbostel.springextjs.viewmodel.SingleGizmoResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

    @Controller
    public class ExampleGizmoController {

        @RequestMapping(value="/gizmos/{gizmoId}", method= RequestMethod.GET, produces=APPLICATION_JSON_VALUE)
        @ResponseBody
        public SingleGizmoResponse getFact(@PathVariable Long gizmoId) throws IOException {
            System.out.println("Gizmo retrieved.");
            return new SingleGizmoResponse(true,new Gizmo(1L,"HELLO"));
        }

        @RequestMapping(value="/gizmos", method= RequestMethod.GET, produces=APPLICATION_JSON_VALUE)
        @ResponseBody
        public ManyGizmoResponse getFacts() throws IOException {
            System.out.println("Gizmo search.");
            List<Gizmo> gizmos = new ArrayList<Gizmo>();
            gizmos.add(new Gizmo(1L, "HELLO"));
            gizmos.add(new Gizmo(2L, "WORLD"));
            return new ManyGizmoResponse(true,gizmos);
        }

        @RequestMapping(value="/gizmos", method= RequestMethod.POST, produces=APPLICATION_JSON_VALUE, consumes=APPLICATION_JSON_VALUE)
        @ResponseBody
        public SingleGizmoResponse createGizmo(@RequestBody Gizmo gizmo) throws IOException {
            System.out.println("Gizmo created.");
            return new SingleGizmoResponse(true,new Gizmo(1L,"NEW GIZMO"));
        }

        @RequestMapping(value="/gizmos/{gizmoId}", method= RequestMethod.PUT, produces=APPLICATION_JSON_VALUE, consumes=APPLICATION_JSON_VALUE)
        @ResponseBody
        public SingleGizmoResponse updateGizmo(@PathVariable Long gizmoId, @RequestBody Gizmo gizmo) throws IOException {
            System.out.println("Gizmo updated.");
            return new SingleGizmoResponse(true,new Gizmo(1L,"UPDATED GIZMO"));
        }

        @RequestMapping(value="/gizmos{gizmoId}", method= RequestMethod.DELETE, produces=APPLICATION_JSON_VALUE    )
        @ResponseBody
        public SingleGizmoResponse deleteGizmo(@PathVariable Long gizmoId) throws IOException {
            System.out.println("Gizmo deleted.");
            return new SingleGizmoResponse(true,new Gizmo(gizmoId,null));
        }
    }


For all of the methods, you’ll the ‘@RequestMapping’ annotation. This annotation is used by Spring for routing requests to individual controller methods. It also contains parameters that tell Spring what type data it can produce/consume and what HTTP verb the operation will be executed with. You’ll also see @RequestBody and @ResponseBody. Those tell Spring that the body of the request or response is to be unmarshalled and marshalled, respectively. By default (using the dispatcher-servlet config above), that format is JSON using the Jackson JSON utility. Let’s take a second to look at the value objects we’re mapping the aforementioned JSON to.

Here we have the Gizmo itself. You can see we’re using some annotations here to provide cues for the Jackson Utility. @JsonAutoDetect tells Jackson how to look at individual fields and which fields to look at. In our case, we’re telling Jackson to look only at those fields with a public accessor method.

package com.rodenbostel.springextjs.viewmodel;

import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonProperty;

import java.io.Serializable;

@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.ANY, fieldVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.ANY)
public class Gizmo implements Serializable {
    private Long id;
    private String description;

    public Gizmo(){}

    public Gizmo(Long id, String description) {
        this.id = id;
        this.description = description;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

Depending on the type of response we’re sending we’re also providing a class to wrap a single Gizmo, and multiple Gizmos. You can see in the source there we’re using the same annotations to instruct Jackson where to find the fields it needs to use.

package com.rodenbostel.springextjs.viewmodel;

import org.codehaus.jackson.annotate.JsonAutoDetect;

import java.io.Serializable;

@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.ANY, fieldVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
public class SingleGizmoResponse implements Serializable {
    private boolean success;
    private Gizmo gizmo;

    public SingleGizmoResponse(boolean success, Gizmo gizmo) {
        this.success = success;
        this.gizmo = gizmo;
    }

    public boolean isSuccess() {
        return success;
    }

    public Gizmo getGizmo() {
        return gizmo;
    }
}


package com.rodenbostel.springextjs.viewmodel;

import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;

import java.io.Serializable;
import java.util.List;

@JsonAutoDetect(getterVisibility = Visibility.ANY, fieldVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
public class ManyGizmoResponse implements Serializable {
    private boolean success;
    private List<Gizmo> gizmos;

    public ManyGizmoResponse(boolean success, List<Gizmo> gizmos) {
        this.success = success;
        this.gizmos = gizmos;
    }

    public boolean isSuccess() {
        return success;
    }

    public List<Gizmo> getGizmos() {
        return gizmos;
    }
}

Our read methods are mapped to ‘GET’ at /gizmos. You’ll notice though, that the getFact method also takes a Path Variable using the @PathVariable annotation. Spring allows you to name path variables in your request mapping ({gizmoId} in this case) and bind them to parameters passed to the underlying method (@PathVariable Long gizmoId). Providing the path variable in the request mapping allows Spring to differentiate the two read methods – “/gizmos/1” will return a single gizmo whose id is 1, and “/gizmos” will return all of the gizmos in the database. Our write methods are mapped in much the same way, but you can see the difference in the HTTP methods they work with.

Fire up the app in your favorite container and head to /spring/gizmos, and experiment with the different calls. You can use a nice little Chrome app called Postman to make different types of calls to exercise the whole interface ahead of our ExtJs development.

Good luck and get ready for Part 2 where we add an ExtJs UI on top of what we’ve just developed!

SpringOne2GX, Day 2 Recap

Another good day at SpringOne.

The first session of the day was with Burt Beckwith going over the Spring Security plugin(s) for Grails. The last Grails work I did was with the Shiro/JSecurity plugin, which worked well, but I’ve always been interested in the extended feature set of Spring Security and it’s extensions. I thought the UI plugin looks useful, and the OpenID support looks like it’s got some nice features. Much of the rest still seems to be up in the air, but it’s maturing nicely. Glad to hear the demo code will be available.

Second talk was on the Google track, and was covering Spring Roo (which I promptly got stoked about yesterday) and it’s integration with GWT. I understand all of the browser compatibility advantages of GWT, but I’m still not convinced the complexity is worth it. Thankfully, Spring Roo does what it does best when it comes to GWT – generates and tucks away your boiler plate code. I’m not as excited about GWT as I thought I would be.

Third talk was with Burt Beckwith again – this time about strategies for handling database migrations in Grails apps. This is an aspect of Rails that I think is far superior to Grails. I didn’t get much from this talk other than how to correctly use Liquibase, but it was good to hear that this is something is being addressed in the upcoming version of Grails.

Fourth talk was about Extreme Scaffolding with Jean Barmash. We saw demos of a few interesting plugins for scaffolding and other UI enhancements, but I didn’t see anything really groundbreaking. It seems that a good command of grails templates, layouts and keeping DRY in mind would accomplish the same thing. It might even take longer to put all of these plugins in, and learn how to correctly use them, rather than just focus on writing good code and pushing out useful functionality.

Finishing the day with Stefan Schmidt and another great talk on the versatile persistence functionality available in the latest version of Spring Roo. The incremental reverse engineering is awesome and blows hibernate right out of the water. Grails and Rails are great for greenfield development, but this really makes Roo a compelling solution for developing new apps on existing databases. The JPA2 and NoSQL support were interesting. The one part I didn’t get was the discussion on Hades. Hades is a Roo add-on that generates the DAOs that Roo is made to get rid of (or at least hide). Maybe I missed something – it sounded interesting – I just didn’t see how it fit with the rest of the features of Roo, other than code generation, of course.

In all, not as good a day as the first, but I learned some interesting things. Spring Roo really seems like an exciting alternative Grails, especially if you’re developing in a dynamic language resistent environment. Looking forward to tomorrow.

SpringOne2GX, Day 1 Recap

It was an interesting day today at SpringOne2GX. There were many interesting presentations – here’s some thoughts on the 5 I attended today:

Guillaume Laforge’s talk on Gaelyk first thing in the morning was very interesting. I’ve been casually following the Gaelyk project for a while and was happy to hear more about it from the project’s founder. It looks like a great toolkit to easily take advantage of all of the features of the Google App Engine using a familiar and concise language in Groovy. A nice departure from Grails, Gaelyk is packed with a lot of interesting options and flexibility being on the Google App Engine. Definitely worth checking out for lightweight web apps with simple persistence needs.

Arjen Poutsma’s talk on the new features of Spring-WS was interesting also – good to see the familiar patterns and usages of Spring MVC making their way into the integration side. I’m currently on a Spring 3 project, and I’m quite sure there’s a compelling reason to roll this in. Definitely looking forward to getting into the details.

The Spring Roo presentation by Rod Johnson was a real eye-opener and definitely renewed my interest in the static-typed side of the Spring ecosystem. Grails, for straight java – what a cool idea. Pseudo-dynamic, clean code with boilerplate code woven in using AspectJ ‘side files’. I can’t wait to fire this one up, although I’m skeptical about how well I will work with it outside of eclipse/STS, which is not my first choice in regards to an IDE. The scaffolded UIs look very impressive. Looking forward to learning more about Roo + GWT tomorrow.

Another interesting Groovy-related talk was by Guillaume Laforge and Paul King on building DSLs with Groovy. A few very cool tricks and what I’m sure will be useful strategies for building DSLs using Groovy.

Wrapped up the day checking on the Grails 1.3 update with Graeme Rocher. Definitely a lot of stuff coming up that will be useful as the framework continues to grow. The GORM implementations at tonight’s keynote were awesome. New dependency management will be nice and clear with the right amount of control.

Looking forward to tomorrow!

Find the Grails in Spring MVC

As I mentioned earlier, I recently moved back to the Java world after a brief and enjoyable foray into Groovy & Grails. After a few minutes of becoming reacquainted with Spring MVC, I found myself wanting to make my Spring MVC app behave more like a Grails app. I’m lazy, what can I say?

The request mapping annotations are the obvious first piece to the puzzle. The second piece is using model attributes. The third is a bit of javascript to get some flexibility in the view. Here we go.

Obviously, the class marked with the ModelAttribute annotation can be an actual model object or a command object.

The controller will look something like this:

/**
 * A simple controller, use it to display and update values in the command object.
 * 
 * @author justin
 */
@Controller
public class SampleController {

	@RequestMapping("/action-to-display-page.do") 
    public ModelAndView displayYourPage() {
		//build your command object
		ModelOrCommandObject modelOrCommandObject = new ModelOrCommandObject();
		modelOrCommandObject.setMessage("Hello world.");
		
		//put your command object in the model map.
		ModelMap modelMap = new ModelMap();
		modelMap.addAttribute("modelOrCommandObject", modelOrCommandObject);
		
		//build your ModelAndView object.
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addAllObjects(modelMap);
		modelAndView.setViewName("some-page.jsp");
		
		return modelAndView;
	}
	
	/**
	 * One of the actions that your page is submits to.
	 * @param modelOrCommandObject
	 * @param result
	 * @param status
	 * @return
	 */
	@RequestMapping("/one-action-to-call.do") 
    public ModelAndView actionOne( 
                    @ModelAttribute("modelOrCommandObject") ModelOrCommandObject modelOrCommandObject, 
                    BindingResult result, 
                    SessionStatus status) {
		//do whatever you need to with your command or model object for this command
		modelOrCommandObject.getMessage();
		return new ModelAndView();
	}
	
	/**
	 * Another action that your page submits to.
	 * @param modelOrCommandObject
	 * @param result
	 * @param status
	 * @return
	 */
	@RequestMapping("/another-action-to-call.do") 
    public ModelAndView actionTwo( 
                    @ModelAttribute("modelOrCommandObject") ModelOrCommandObject modelOrCommandObject, 
                    BindingResult result, 
                    SessionStatus status) {
		//do whatever you need to with your command or model object.
		modelOrCommandObject.getMessage();
		return new ModelAndView();
	}
}

We’ll have the option in the view to map one action to the controller or multiple actions. Multiple actions is easy with a bit of javascript.

The jsp will contain code like this;

<form:form action="/myapp/one-action-to-call.do" method="POST" modelAttribute="command" method="POST">
<!– some form fields –>
<button onclick="this.form.action=’/myapp/one-action-to-call.do’;submit()">One action</button>
<button onclick="this.form.action=’/myapp/another-action-to-call.do’;submit()">Another action</button>
</form:form>

That’s been working well for me as a simple bridge between Spring MVC and *some* of the convenience and efficiency of grails.