Friday, July 29, 2011

Getting started with Spring Roo, GWT and STS - Part 1


This is a multi-part article. This article walks through my experiences getting started with spring's Roo framework using the Spring Tools Suite (STS). The next articles will walk through different aspects of building an application from scratch.
Also see

  • Part 1 - Install and create - back end (this blog)
  • Part 2 - Web MVC
  • Part 3 - GWT
  • Part 4 - Custom app from scratch



Part One - Getting started with Roo using STS - The Roo tutorial 

Time to get started. I'm going to run through the introductory materials on building a Spring Roo application using the Roo tutorial. In the next articles I will build a custom example using Spring Roo with the Google Web Toolkit front end. I will be using the Spring Tools Suite as the IDE (based on Eclipse).

I will start by following some initial advice:
Installation

What I have
  • Java 6 SDK r26 from here
  • Running on a Windows 7 Laptop (64 bit)
Step 1 - Install STS  
Download from here and follow the simple instructions.
I installed SpringSource Tool Suite: Version: 2.9.0.RELEASE Build Id: 201203011000

Step 2 - Configure to use Google Web Toolkit and Google App Engine
After running STS, go to the dashboard and select the 'extensions' tab (bottom). Find and Check Google Plugin for Eclipse and press 'Install' (bottom left)

Restart STS and thats it (for now)

Running through the Spring Roo Tutorial

Overview of Spring Pizza Shop Demo
Lets use the Spring Framework Roo tutorial to get started.This tutorial walks us through creating a Roo project including entities controllers and the UI/scaffold. I will try to emphasise use of the STS tool as well as focusinging on using GWT as the front end. To begin with, we will follow the tutorial fairly closely.

Here is the project UML from the spring tutorial that we will create



This is the Roo Pizza Shop demo













First Step Basic Roo Configuration

Spring Roo builds upon Spring framework 3.0 with JPA 2.0. It uses a command line tool to create basic elements of a project, from persistence setup, to creating entities, to creating Spring MVC controllers, to generating Scaffold ui (later we will be using GWT).


We can use spring STS to create a new spring Roo project project


  1. From the Dashboard, select Create a Spring Roo Project
  2. Fill out dialog: Project Name: pizza, top level package: com.springsource.roo.pizzashop
  3. Accept all other defaults and press Next (and then Finish). This will create the Roo project and open the roo shell. Actually, STS is executing the roo shell to create the project directory and the roo command:
    roo> project --topLevelPackage com.springsource.roo.pizzashop
We see the ROO command shell at the bottom with a command promt inviting us to execute roo commands.

Note: Using the Roo shell in StS 

Roo uses a shell similar to Rails to invoke commands that create essential structures and configurations around the Roo project. It saves a lot of time writing repetitive code or digging around to configure stuff. the shell is a bit smart in that it knows what you have done in your project and what steps can be next.




The window has a top part showing a console with roo commands as well as a prompt, but don't be fooled. The roo prompt we use in StS is below (a single line edit).
The spring ROO project leverages Maven2 and its unique project structure.

One cool roo command you will use right away is hint. This will give you possible options to do from the point in your project.

After creating a roo project, you can type HINT in the Roo shell. It will respond with:

Roo requires the installation of a JPA provider and associated database.

Type 'persistence setup' and then hit CTRL+SPACE three times.
We suggest you type 'H' then CTRL+SPACE to complete "HIBERNATE".
After the --provider, press CTRL+SPACE twice for database choices.
For testing purposes, type (or CTRL+SPACE) HYPERSONIC_IN_MEMORY.
If you press CTRL+SPACE again, you'll see there are no more options.
As such, you're ready to press ENTER to execute the command.

Once JPA is installed, type 'hint' and ENTER for the next suggestion.
It knows what you have done before so it can provide hints for the next steps. Very smart!

Next: Setup project with persistence library

As mentioned before, Spring Roo requires the configuration of a JPA provider such as Eclipselink,, OpenJPA or Hibernate.

configure persistence for this project: in Roo shell,
  1. As explained above, type hint and roo will prompt you to setup persistence for your project
  2. type' persitence setup' and press ctrl+space. In StS, this will use code assist to allow you to select possible next options for the command (the command line, you press the TAB key). In this case we will select --provider HIBERNATE and --database HYPERSONIC_IN_MEMORY
  3. The complete roo command is:
    persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY
    
  4. Roo will generate the JPA configuration files and initial spring context

Note: the roo log file

Spring keeps a log of your commands in the root project: log.roo. This may be handy to track what you have done, and in fact can be re-executed line by line to repeat your steps.

Next: Create your first Entity

In JPA, classes annotated as Entity are persistable, and generally map one-to-one to a table. Class properties generally map to columns in that table. The first class we will create will be Topping (see above UML model).

Using Roo shell:
  1. Type Hint again, and Roo will advise you to type ent and press TAB to get the next option (from STS, ctrl+space). This will allow us to create an entity with a specific class name: Topping
  2. Type entity then press (ctrl+space) . This will produce --class
  3. Type ~.domain.Topping for the class name (the tilda will indicate the project's package root (remember we specified com.springsource.roo.pizzashop)
  4. Now ctrl+space doesn't give us more hints since all required options are satisfied, but type double dash (--) and then ctrl+space will give us a bunch more options.
  5. type or select --testAutomatically to generate test classes for the new entity and press enter
 (the complete roo command: entity --class ~.domain.Topping --testAutomatically)

Roo creates a whole bunch of files and aspects. Notice the actual entity "SRC_MAIN_JAVA\com\springsource\roo\pizzashop\domain\Topping.java" is created. You can see it in the packag tree. However, STS starts with an inital filter in the package tree to 'Focus on Active Task'.

Click the filter icon in the top toolbar of the Package view to reveal the entire project. Now navigate to src/main/java. See the com.springsource.roo.pizzashop.domain package and the created Topping.java class just created.

Next: Create Fields for Our Entity

Now lets add a field.
Use the roo command to type:


  1.  field string --fieldName name --notnull --sizeMin 2

This will add a field, and update/add to the generated aspects based on the annotaitions.

Opening this class, all you see is

File: Topping.java
package com.springsource.roo.pizzashop.domain;  
import org.springframework.roo.addon.entity.RooEntity; 
import org.springframework.roo.addon.javabean.RooJavaBean; 
import org.springframework.roo.addon.tostring.RooToString; 
import javax.validation.constraints.NotNull; 
import javax.validation.constraints.Size;  
@RooJavaBean 
@RooToString 
@RooEntity 
public class Topping { 
     @NotNull
     @Size(min = 2)
     private String name; 
} 


Notice the classs annotations that roo adds @RooJavaBean, @RooToString and @RooEntity. These annotations generate aspects with extensions .aj for inter type definitions. Spring also adds JSR 303 bean validation annotations on the field based on the options we specified: @NotNull and @Size(min = 2).

The principle that Roo introduces here is the heavy leveraging of AspectJ's Inter-Type Declaration (ITD). The ITD code generates as a separately complied file, but is encorporated into the class byte code of the advised class. Generally we don't need to bother about what is generated here. But lets look anyway. For instance, the @RooJavaBean annotaion creates the class Topping_Roo_JavaBean.aj. Peeking at it, we see:
File: Topping_Roo_Entity.aj
// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO. 
// You may push code into the target .java compilation unit if you wish to edit any member(s).  
package com.springsource.roo.pizzashop.domain; 

import java.lang.String; 

privileged aspect Topping_Roo_JavaBean { 
    public String Topping.getName() { 
        return this.name; 
    }     

    public void Topping.setName(String name) { 
        this.name = name; 
    }      
}  


We see that the name field produced a getter and a setter for the field. As we add new fields, this aspect will be updated. Using aspects this way allows the domain class to remain particularly pure.

As another example, lets look at what was generated for the @RooToString annotation:

File: Topping_Roo_ToString.aj

package com.springsource.roo.pizzashop.domain;  
import java.lang.String;  
privileged aspect Topping_Roo_ToString {      
    public String Topping.toString() { 
        StringBuilder sb = new StringBuilder(); 
        sb.append("Id: ").append(getId()).append(", "); 
        sb.append("Name: ").append(getName()).append(", "); 
        sb.append("Version: ").append(getVersion()); 
        return sb.toString(); 
    } 
}



Pretty nifty, huh! this is the Secret Sauce of Roo as described in Ben Alex' Blog on Roo's Architecture

Finally, lets' look at what Roo does with the @RooEntity declairation
File: Topping_Roo_Entity.aj

// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO.
// You may push code into the target .java compilation unit if you wish to edit any member(s).

package com.springsource.roo.pizzashop.domain;

import com.springsource.roo.pizzashop.domain.Topping;
import java.lang.Integer;
import java.lang.Long;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PersistenceContext;
import javax.persistence.Version;
import org.springframework.transaction.annotation.Transactional;

privileged aspect Topping_Roo_Entity {
    
    declare @type: Topping: @Entity;
    
    @PersistenceContext
    transient EntityManager Topping.entityManager;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long Topping.id;
    
    @Version
    @Column(name = "version")
    private Integer Topping.version;
    
    public Long Topping.getId() {
        return this.id;
    }
    
    public void Topping.setId(Long id) {
        this.id = id;
    }
    
    public Integer Topping.getVersion() {
        return this.version;
    }
    
    public void Topping.setVersion(Integer version) {
        this.version = version;
    }
    
    @Transactional
    public void Topping.persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.persist(this);
    }
    
    @Transactional
    public void Topping.remove() {
        if (this.entityManager == null) this.entityManager = entityManager();
        if (this.entityManager.contains(this)) {
            this.entityManager.remove(this);
        } else {
            Topping attached = Topping.findTopping(this.id);
            this.entityManager.remove(attached);
        }
    }
    
    @Transactional
    public void Topping.flush() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.flush();
    }
    
    @Transactional
    public void Topping.clear() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.clear();
    }
    
    @Transactional
    public Topping Topping.merge() {
        if (this.entityManager == null) this.entityManager = entityManager();
        Topping merged = this.entityManager.merge(this);
        this.entityManager.flush();
        return merged;
    }
    
    public static final EntityManager Topping.entityManager() {
        EntityManager em = new Topping().entityManager;
        if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
        return em;
    }
    
    public static long Topping.countToppings() {
        return entityManager().createQuery("SELECT COUNT(o) FROM Topping o", Long.class).getSingleResult();
    }
    
    public static List Topping.findAllToppings() {
        return entityManager().createQuery("SELECT o FROM Topping o", Topping.class).getResultList();
    }
    
    public static Topping Topping.findTopping(Long id) {
        if (id == null) return null;
        return entityManager().find(Topping.class, id);
    }
    
    public static List Topping.findToppingEntries(int firstResult, int maxResults) {
        return entityManager().createQuery("SELECT o FROM Topping o", Topping.class).setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }
    
}

}



Rather than creating a data access object (DAO) or service, Roo assumes that each entity created has its own implementation of persistence. The @RooEntity annotation generates a ITD (Inter-type Declairation) for the entity advising it to add many methods to support persistence, inclding id generation, versioning, access to the entity manager, various transactional methods:

  • persist,
  • remove,
  • flush,
  • merge,
  • clear
and various finder methods

  • count
  • find by id
  • findAll
  • and pagable findAll



Next: Some More entitles and fields

As Roo creates objects, it keeps track of the last object you created. The next command defaults to this target, so there is no need to specify it explicitly. For example, when we created the field, we didn't need to specify what class to create the field for. It assumed we meant the last entity we worked with.. The spring Roo console shows what entity we last worked with in its prompt, much like a command shell might with a prompt showing the current directory path.

Using roo shell:

Now lets create another entity and some fields similar to the ones we created before. Here are the Roo commands:

entity --class ~.domain.Base --testAutomatically 
field string --fieldName name --notNull --sizeMin 2
entity --class ~.domain.Pizza --testAutomatically 
field string --fieldName name --notNull --sizeMin 2
field number --fieldName price --type java.lang.Float




That's it. As long as we follow the defaults, things are easy. This is the approach taken by Ruby on Rails: convention over configuration. The command line invokes templated commands to create objects quickly.

Our project should look basically like this (as seen from the project view)


Next: Some Relationships for our Entities


We are still in JPA land. JPA allows us to create relationships as well as if POJO java classes using well known collections. Roo supports a one-to-one or many-to-one reference, a one-to-many 'set' (and also ways to create many-many). In the above, we have a one-many relationship from Pizza to Topping (a pizza has many toppings) and a one-one relationship (reference) to a base. We'll use the Roo command shell to create these too. The tutorial shows there are two relationships from Pizza, a 'reference' to a base (m:1) where a Pizza has one base, and a set of toppings (m:m relationship to toppings), where a pizza has a set of toppings.

In roo shell, type the following:

field set --fieldName toppings --type ~.domain.Topping
field reference --fieldName base --type ~.domain.Base


The above commands assume you are creating the relationship fields to the last entity you created: Pizza as it would show you in a command prompt. If not, make sure to append --class ~.domain.Pizza to the above commands (at least the first one) to assure the relationships are created for the Pizza class.


And we can finish up with PizzaOrder, in roo shell:


entity --class ~.domain.PizzaOrder --testAutomatically
field string --fieldName name --notNull --sizeMin 2
field string --fieldName address --sizeMax 30
field number --fieldName total --type java.lang.Float
field date --fieldName deliveryDate --type java.util.Date
field set --fieldName pizzas --type ~.domain.Pizza

Note: if you make a mistake, you cn press the up arrow from the Roo shell prompt in STS and previous commands can be edited and re executed.

Notice the last command creates another relationship, this time an PizzaOrder has a set of Pizzas ordered, which Roo will create a m:m relationship for of type Set pizzas. As you can see, creating entities, fields and relationships with Roo comes down to running a set of commands to generate the appropriate Java code and Aspects according to Roo convention. In fact, you can save these commands as a 'seed' text file that will create a project for you, generating the project structure, configruation, classes and aspects required.


Next: Lets Test


We can now run the integration tests using the roo command perform tests.
perform tests


Here is a summary of the roo commands executed
// Spring Roo 1.1.4.RELEASE [rev f787ce7] log opened at 2012-03-17 10:38:04
project --topLevelPackage com.springsource.roo.pizzashop --projectName pizza --java 6
// Spring Roo 1.1.4.RELEASE [rev f787ce7] log closed at 2012-03-17 10:38:15
// Spring Roo 1.1.4.RELEASE [rev f787ce7] log opened at 2012-03-17 10:38:19
hint
hint
persistence setup --database HYPERSONIC_IN_MEMORY --provider HIBERNATE 
hint
entity --class ~.domain.Topping --testAutomatically 
field string --fieldName name --notnull --sizeMin 2
entity --class ~.domain.Base --testAutomatically 
field string --fieldName name --notNull --sizeMin 2
entity --class ~.domain.Pizza --testAutomatically
field string --fieldName name --notNull --sizeMin 2
field number --fieldName price --type java.lang.Float

field set --fieldName toppings --type ~.domain.Topping
field reference --fieldName base --type ~.domain.Base
entity --class ~.domain.PizzaOrder --testAutomatically
field string --fieldName name --notNull --sizeMin 2
field string --fieldName address --sizeMax 30
field number --fieldName total --type java.lang.Float
field date --fieldName deliveryDate --type java.util.Date

field set --fieldName pizzas --type ~.domain.Pizza
perform tests



Finally: Look at the test classes generated


The main class 'Pizza' has a name (required min size 2) and a price, but also two relationships: one a many-many relationship to Toppings class and a reference (many-one) relationship to Base class.


File: Pizza.java
package com.springsource.roo.pizzashop.domain;

import org.springframework.roo.addon.entity.RooEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Set;
import java.util.HashSet;
import javax.persistence.ManyToMany;
import javax.persistence.CascadeType;
import com.springsource.roo.pizzashop.domain.Topping;
import com.springsource.roo.pizzashop.domain.Base;
import javax.persistence.ManyToOne;

@RooJavaBean
@RooToString
@RooEntity
public class Pizza {

    @NotNull
    @Size(min = 2)
    private String name;

    private Float price;

    @ManyToMany(cascade = CascadeType.ALL)
    private Set toppings = new HashSet();

    @ManyToOne
    private Base base;
}


The class 'Base' has a single field 'name' but annotated with @NotNull and @Size min 2.

File: Base.java
package com.springsource.roo.pizzashop.domain;

import org.springframework.roo.addon.entity.RooEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@RooJavaBean
@RooToString
@RooEntity
public class Base {

    @NotNull
    @Size(min = 2)
    private String name;
}

Topping is also a simple class, with one field 'name' declaired as Min 2 (but not NotNull ?) probably should be NotNull, dont you think?

File: Topping.java
package com.springsource.roo.pizzashop.domain;

import org.springframework.roo.addon.entity.RooEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import javax.validation.constraints.Size;

@RooJavaBean
@RooToString
@RooEntity
public class Topping {

    @Size(min = 2)
    private String name;
}

Finally, PizzaOrder is the workhorse of the project. It relates the person ordering (this could be another class 'Customer' but isn't for simplicity sake (we may not need to track people or order pizza but it may help down the road)

File: PizzaOrder.java
package com.springsource.roo.pizzashop.domain;

import org.springframework.roo.addon.entity.RooEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Set;
import com.springsource.roo.pizzashop.domain.Pizza;
import java.util.HashSet;
import javax.persistence.ManyToMany;
import javax.persistence.CascadeType;

@RooJavaBean
@RooToString
@RooEntity
public class PizzaOrder {

    @NotNull
    @Size(min = 2)
    private String name;

    @Size(max = 30)
    private String address;

    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "S-")
    private Date deliveryDate;

    private Float total;

    @ManyToMany(cascade = CascadeType.ALL)
    private Set pizzas = new HashSet();
}

Fixing a problem
In the above example, i noted that Toppings 'name' field doesn't have a @NotNull annotation and it probably should. How do you fix it? Using the Roo shell is good for adding stuff, but not changing or removing stuff. To do this, just go to the java code itself.


  1. Open the Toppings class
  2. Add the @NotNull annotation
  3. Add the import for the annotation (I like to use CTRL+SHIFT+O for 'Organize Imports' in the Source menu)
And that's it!


Next steps

On next blog article we will add a user interface to this to complete the tutorial, still no GWT yet. That will be following.

Friday, July 8, 2011

Testing my RESTful controllers with Spring RESTtemplate

I have been playing with Spring's RESTtemplate as an approach to integration testing on my project.

Overview of Testing a RIA with Spring and Spring MVC



I feel I should create a set of blog posts related to how I am doing testing with this technology stack. Sometimes this aggregation is helpful. In my team, we are testing at the following levels:

  • unit testing of everyting - pure tests, typically single class only, with mock (using Mockito)
  • integration testing of our services - out of container (web server) testing, but with db
  • integration testing of our controllers - in container testing, with db
  • functional testing of our ui (TBD) - full in container testing


This blog will focus on integration testing.

Integration testing, different from unit testing, tests the code as it is wired up to other components, the server and the data base as well.

Testing the controller layer in Spring MVC



To set the stage, I am using spring 3 with Spring MVC for my application. In particular, I am leveraging a lot of Ajax, accessing the controller from the browser and transporting JSON. I am using the Jackson JSON mapping implementation to marshal to from beans to JSON.

I need to create good integration tests of my controller classes so I can run JUnit tests that connect with the deployed web app and interact RESTfully like the client UI, passing JSON objects back and forth.

A helpful blog post I have used for guidance: is ralf.schaeftlein s blog detailing an approach to integration testing of restful MVC controllers with JSON. Exactly what I was interested in.
The basic steps seem to be:
  1. create a unit test with java4 leveraging Spring 3 Integration Test Annotations
  2. configure your application context XML to define your mappers that will convert between JSON and beans
  3. write your tests pojo style
Integration Testing with Spring uses annotations to supply a spring context to your test code. Further, the annotations specify what transaction manager to use and if a rollback should be performed after the test is complete. The tests itself are written with JUnit4. Here is a snippet showing the annotations required placed on your test class.


In this case, I am testing my Data Repository, which is essentially my Data Access Object (DAO) for you old schoolers. I will post why Repositories and not DAO in a future blog.
My application context file configures spring with the required setup for my application to run this test. First, the usual name spaces:

Then, we use automatic annotation discovery of out project

Here is wshere we configure the restTemplate to be used for this integration test of our controller
Finally the required configuration for our persistence. Notice we are using JPA configuration here


Finnaly the test code.

We write an integration test for our controller that connects remotely to the deployed application, sends beans mapped from Pojo to json for the call, and then maps back json to Pojo to assert results.

A shout out to a framework for html5

One of my readers sent me a link to Strobe, (http://www.strobecorp.com/) an open source platform built from the ground up to leverage html5, but still leverage MVC. Although my ship has already left down the river of Spring, I can longingly look at its innovation and see what we can adopt for ourselves. I know I will loose a few hours this weekend on playing with this one.

Thanks

PS, I also seem to be wasting my time playing with knew language ides: ever check out Clojure. Yes, it talks with a lisp as well.

Crossing the chasm to the new paradigm

I titled this post in homage to Moore, the author of Crossing the Chasm. He clearly described how marketing strategies for high-tech are different from other product categories. He heavily leverages the technology adoption life-cycle bell curve where Rogers et. al. segments people into 5 categories:
  1. innovators,
  2. early adopters,
  3. early majority,
  4. late majority and
  5. laggards
(although the last category seems a bit offensive :)). Moore emphasizes that getting from early adopter to early majority is like crossing a chasm: the former 'visionaries' have very different expectations then the later 'pragmatists'. To mix authors (like metaphors), a 'tipping point' seems to be required to make the shift.
So it is for developers: new ideas, languages and techniques come by all the time. Some jump in 'where angels dare to tread'. I seem to be the former. At least I like to think of myself as such. Others wait. Some are clearly risk averse, but I think for some, it is hard to let go of the 'it works, why change it' paradigm. Perhaps they are right. They are pragmatists, and by nature practical. But innovators and early adopters seem to reap benefits. Since the technology wave moves incesntly and swiftly, it is best to keep on its cusp, like a surfer, using its power and momentum to guide you on, lest you be left paddling to catch up, far behind.
But many on my team aren't of the innovator ilk. Nor is my company. I work for a very large software company that should be on the leading edge, if not the bleeding edge of innovation adoption. But we're not. We suffer from a stifling bureaucracy (like most large companies or governments, dare I say), and a hefty dose of 'not built here' syndrome. Interestingly enough, by boss isn't a 'laggard' in any stretch of the imagination. He, however, bears the brunt of having to argue for the wacky ideas of his reports in front of very risk averse corporate gatekeepers. Sometimes he wins, sometimes not.
But, within the team, it was surprising to me how shocked people were when I said,
"we are not going to write JSP any more."

I'm sure some of the readers of this blog post (all 1 of you) might be shocked as well. But sometimes we need to be shocked. This is a broad and sweeping statement, but it is powerful, because it hints at our reliance on rendering the UI on the server. And we shouldn't. This is heresy, and would have been foolish in the past. From early cgi and perl (remember those days) to the development of J2EE, the browser was considered a dumb reader of html, not a smart client platform like thick client apps or client server. Applets were to be that, not the browser. If not Applets, then flash, if not flash then... well, ... the browser.
What is the browser today? Its not dumb. It's not just a reader. It is an operating system. It is a platform that has capabilities to run sophisticated programs delivered to it. HTML5, CSS3 and JavaScript are the languages it speaks. If you know the lingo, you can unleash a vast array of capabilities that just a couple of years before were left to the native or thick client world.
So, my aha moment came when I realized that what we needed to do was to go back to the client server days. In those days, you had vast power of the desktop, its graphical and multimedia power and local storage capability. You connected to the server for data. Yes, business rules and shaping of data occurred on the server. Certainly secure selection and delivery of data as well. It enforces transactionality and validity. It handles persistence and auditing. But its is never in the business of rendering the user interface--that's the client's job.
Rendering UI on the server was the compromise required to deliver applications over the web. And it was worth it too. Not to wory about the client footprint, not to have to wait for support to install and configure the next version. immediate access to everything a mouse click away. It rocked our world. It changed our world. Thanks Tim for that. But he was thinking hyperlinked books after all, not applications. It was amazing what we can do even with its obvious limitations. And Tim has moved on too.

But we no longer need to make this compromise. We can benefit from the zero footprint immediate access to all the worlds knowledge and applications but still leverage graphics, multimedia, processing power and even local storage of the desktop.

Wednesday, July 6, 2011

Fun with HTML5

I guess I'm a bit late to the game. However, perhaps not too late. HTML5 offers a host of solutions for the kind of application I want to build: rich client, local storage, animated, etc. I walked through several HTML5 demos and examples over the weekend.
I can deliver a rich client experience for an application needing local only storage with nothing but HTML5, JavaScript and CSS3. But for real 'client server' or mashups with shared information, we still need connectivity to the server (Ajax based, RESTful, transport in JSON).

Sunday, July 3, 2011

New Technology Stack

In my real life, I actually have to deliver software :). So most of my blogs are about the technologies I am using today as well as best practices I am actually practicing (or trying to practice) in my real life.
This blog will focus on the following technology stack for now:
Also I will be looking at:
Some techniques and tools include
  • Sun NetBeans IDE
  • SpringSource Tool Suite
  • Test Driven Development
  • Continuous Integration
  • Maven


Back again and focusing on Enterprise 2.0

Why did I rename this blog Enterprise 2.0 Appplication Tecchnologies?

I am not abandoning ECM and SOA, but I am expanding to incorporate a more generalized concern.

To me, enterprise 2.0 is bringing the promise of web 2.0 to enterprise applications. Not just in providing a better social experience, but providing a better user experience in general, with more user centered and natural user interfaces.

Since Sun quoted "the network is the computer", many (myself included) have been trying to find a way to build enterprise applications that have a rich client experience but are not locked into a heavy installation footprint. Conventional web development has allowed us to build Software as a Service (SaaS), minimizing client and installation requirements and maximizing availability. But on the other hand, these applications are typically designed for the least-common-denominator, heavy on server side processing, have very unnatural user experiences, are constructed with a cacophony of languages, and tend to be a slave to bandwidth and availability of the network.

An ignorant corporate sponsor might ask "Why can't we have the rich user experience of the desktop while leveraging the ubiquity of the web?"

Well, now we can. Through the power of JavaScript and HTML5 the browser can support truly rich client experiences, while still leveraging the advantages of the web and being available anytime, anywhere on any device. Constructing access to information and actions using the power of REST and semantic net, different user experiences can be developed to share and leverage the knowledge of the enterprise in different ways. And still the enterprise applications can leverage well tested legacy services, be secure and achieve the availability and performance requirements demanded by the corporation.

However, I am still concerned with requiring constant connectivity. Most of even the best internet applications that deal with transitional data require continuous high bandwidth connectivity to the services. Especially for the mobile worker (an ever increrasing demographic), being able to work 'off-line' sometimes is essential.

So, my search for the answer to the question "Why can't we have the rich user experience of the desktop while leveraging the ubiquity of the web?" includes the following:
  • Rich client experience supporting many user types and many devices, including the use of graphics, multimedia and alternate input technologies
  • Secure access to semantically rich resources and services that are flexible and can be leveraged from many different clients
  • Connectivity to other legacy systems and services, supporting synchronous and asynchronous models
  • Mechanisms that allow users to share and collaborate and work off-line as well as on line
We want secure access to corporation's transactional information and services available at any time, from anywhere on any device, while allowing users to organize their own experiences and collaborate with others the way they want to.

The purpose of this blog is to try to address these concerns and others through technology available today, relevant to my own direct work requirements as well as the purely theoretical.