ExtJs

As a reviewer…

One of the other things I spent time on last year was acting as a reviewer for a book that was recently published by Packt Publishing. I was approached by Packt early in the summer to volunteer to help review a work in progress called Enterprise Application Development with Spring and ExtJs. I was skeptical at first, so I did some research. Easily the majority of blog and message board content on the subject of being an unpaid reviewer, especially for Packt for some reason, was negative. This was an obvious red flag. However, I read a fair number of technical books, and I do enjoy writing, so I thought it might be an interesting thing to participate in, especially if I ever wanted to be an author in the future. In the back of my head I knew that if it became too much, especially given that it was volunteer time, that I could simply back out. I agreed to participate and off we went.

Here’s the basic deal: you get a couple of chapters to go through every 4 days. They give you a questionnaire to fill out with your comments. The publisher encourages feedback on many different levels – sentence structure and grammar, chapter-level organization and content, even the order of the chapters and higher level things. All fairly reasonable.

In all, I didn’t have a problem with the process. It was very interesting to see a book as a work in progress. By the time I was involved, it was clear the tools, table of contents and topics covered were fairly well set. Obviously, getting paid would have been nice, but I knew I was volunteering (well, I was getting a free ebook). I also knew the subject matter, which made things much easier. I was able to bypass the learning part of reading the book and focus on the content, how it was organized, and what type of an experience a reader would have with it.

On the book itself – it’s not bad, it’s just presented in a way that would be hard for me, personally, to digest. For a topic like this, I like to start with a clear goal – working through a project to learn a new technology. Additionally, I prefer consuming new information in small pieces and repeating that consumption, reinforcing foundational concepts while slowly increasing complexity, all the while verifying my progress with test cases. Some examples of books written in this fashion that I enjoyed: Agile Web Development with Rails, Grails in Action. This book is presented in a very waterfall-ish way in the name of Enterprise Application Development, and I think this is where I had the hardest time. Developing apps in the Enterprise does not require big up-front design or a waterfall development methodology. The reader is consuming huge new pieces of knowledge in each chapter, and we’re not doing anything to verify them as we go. The book has the reader waiting for a few layers of the application to be developed before performing integration tests. My concern here is that a reader will be trying to troubleshoot something they wrote two chapters ago, and that they just learned within the last few hours. That sounds frustrating!

Side note: I wasn’t a huge fan of the tools used in the book either. I feel like they are complex enough to be a distraction, that there are more modern/simple choices (Ivy, Eclipse, Spring Data) that would have possibly let the reader focus more on learning Spring and ExtJs.

In short, it was a great experience, I’m glad I did it, and I learned a lot, but if I ever do this again, I’ll make sure my own views and development/learning style are in better alignment with the author’s goals for the book.

Advertisements

Tips For The ExtJS Beginner

If you haven’t already, learn more about Javascript before you start
I wrote a decent amount of Javascript before I started using ExtJS. I’ve used Prototype, jQuery, & Dojo, but I’ve never written as much Javascript as I have on this project, and I’ve never unit tested any Javascript I’ve written until now. The learning curve for ExtJS is not steep, but first learning the basics of Javascript – best practices, common mistakes, design patterns – will drastically improve the quality of your code. You can write a fully-functioning and beautiful ExtJS app in messy and error-prone Javascript. I recommend Javascript: The Good Parts (http://shop.oreilly.com/product/9780596517748.do) and Javascript Patterns (http://shop.oreilly.com/product/9780596806767.do) for reading. I also use a JSHint plugin in my IDE, and I use Jasmine and Phantom for unit testing. I also recommend rolling the execution of each of these into your project’s CI process.

Read the License Agreement
The license agreement changed a few times early in the life of ExtJS, and can be restrictive depending on how you intend to use the product. The Sencha licensing FAQ site does a good job explaining the specifics. https://www.sencha.com/store/licensing-faq/

Use Sencha CMD
Several tools that are packaged with ExtJS require the app to be organized in a specific way. It is possible to use a custom directory structure for your application, but it can be a maintenance concern in the long term as the framework matures and is upgraded. For instance, in the last two upgrades, 4.0->4.1 & 4.1->4.2, the expected structure of the app changed significantly as new tools and concepts are introduced. The example that comes to mind in the last upgrade was the introduction of packages. Starting your project by creating an app using the Sencha CMD tool, and then using it to upgrade the app (which then is responsible for changing the app’s directory structure, if necessary) can be a major time saver.

Use Refs
Not only do they give you conveniently named accessors for view elements to use in place of lengthy dom queries, but they give you a level of abstraction – limiting references to a potentially changing UI/DOM to one place, and saving the price of continual DOM queries by holding references to DOM elements.

Use the framework to build your UI, don’t build a UI and then try to use the framework
Don’t fight the framework. If you’re working with a UI/UX person, be sure they are at least familiar with ExtJS and have read through the examples. Building interfaces using ExtJS constructs as the building blocks instead of building an interface and forcing the framework behind it can save a lot of time and go far in managing the expectations of users.

Be sure you know which browsers you’re supporting and test in all of them
ExtJS is cross-platform, but like almost anything, there are performance differences and gotchas – mostly in IE8 and IE9 – that you need to watch for. The performance issues are expected, but there are some functional differences as well. The two that come to mind are animation issues and issues detecting native Javascript functionality. Test in all of your supported browsers early and often.

Extend base classes, do not edit them
Occasionally, there will be the need to tweak how base classes function to suit your needs or to make up for default functionality that changed between versions of the framework. To save yourself from upgrade pain in the future, use Ext.override (http://docs.sencha.com/extjs/4.2.1/#!/api/Ext-method-override) and change only what you need to change and only where need it. This will prevent any undesirable behavior in places where the out of the box functionality does suit your needs, and/or where it is used internally by the framework.

Do not be afraid to dig into the source
You will see cryptic error messages, and sometimes they’ll originate from Ext files rather than those of your app, especially if they happen while the app is starting up. Learning how to navigate the source while debugging and also from the API docs is a great help. The source is obviously the truth for what is happening in the framework, but also serves as a great location to find implementation examples that you can use in your app.

Grid performance
In our application, we have only one source of consistent performance issues in ExtJS – data grids. The main thing to keep in mind is the amount of time it takes to render the full width and height of the grid. If you need to load a lot of data in your grid, limit the amount of data that is rendered by using the buffered renderer plugin (http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.plugin.BufferedRenderer). Also, try to limit the number of columns in your grid either by not displaying them at all, or by allowing the user to configure what is displayed. Both of these will help prevent unnecessary rendering of off-screen elements when the grid is rendered and re-rendered (for instance, when the window is resized).

Learn to read the API docs
The ExtJS API is quite rich, and learning how to read the API will help you be productive every day. The docs are presented in a very slick way, and allow you to quickly search for classes, filter elements within a class, view the source from any listing in the API doc, and they include working examples.

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!