Cloud Computing and Enterprise POJOs
Chris Richardson

Run Java Applications on Amazon EC2

My book

Calendar

««Jul 2009»»
SMTWTFS
    1234
567891011
12131415161718
19202122232425
262728293031

My Top Tags

                                                                               

My RSS Feeds








 

I am the founder of Cloud Foundry, which provides automated, outsourced data center management for Java applications on Amazon EC2.

I am the founder of Cloud Tools, which is an open-source project for automating the deployment of Java and Grails applications on Amazon EC2.

I run a training and consulting company that helps organizations build better software faster and deploy it on the cloud.

We provide a variety of services including:

  • Development - we can build your application for you
  • Deployment - we can find a hosting partner or deploy your application on Amazon EC2
  • Training classes for Spring, Hibernate and Acegi Security
  • Jumpstarts to get your project off to the right start
  • Reviews to improve your architecture, code and development process

For more information contact me.

 

My bookmarks

Mailing List

Latest Entries

Dynamic Languages: the next big thing for the JVM or an evolutionary dead end?

Wednesday, 15 April 2009 7:15 A GMT-08

Last month I gave a couple of talks at Community One East in NY. One was about running Java applications on Amazon EC2. The other was about dynamically languages vs. static languages and why I am very interested in Scala, which is a modern programming language that is statically typed yet very expressive. In the presentation I talk about my experiences using Groovy (good and bad) and some of the interesting features of the Scala language.

 Here are the slides:

Upcoming events: Oakland Java SIG and SDForum's Shaping the New Age of Application Development

Friday, 10 April 2009 8:29 A GMT-08
Next week, I'll be going to a couple of interesting events. On Wednesday April 15th the Oakland Java SIG (I'm the co-chair) is having its April meeting. The topic is using Mule to integrate applications in the Enterprise and Cloud. And, on Friday and Saturday is SD Forum's Shaping the New Age of Application Development conference. I'll be participating in a panel on cloud-enabled applications. I hope to see you at one of these events.

Progressive Web Tutorials, May 11-13th, London - Running Java and Grails on Amazon EC2

Wednesday, 8 April 2009 8:29 A GMT-08

Progressive Web Tutorials In May, I'll be giving a 1/2 day tutorial on running Java and Grails applications on Amazon's Elastic Compute Cloud. This will be part of Skills Matter's Progressive Web Tutorials. Other tutorials at the event include Dojo Data, Grids, Charts and Comet by Dylan Schiemann, and Introduction to Adobe Flex by Peter Elst. This will be my first time giving a talk in my home country in a very, very long time and I am looking forward to it. I hope to see you there.

tags:              

Groovy and Grails meetup and presentations on running Java on Amazon EC2

Monday, 23 February 2009 4:20 P GMT-08

This is week 2 of a busy few weeks of events and presentations. Last week, I gave my first 1/2 day class on running Java applications on Amazon EC2. It went extremely well with a great turnout. Tonight in Oakland is the SF Bay Area Groovy/Grails meetup. Tomorrow, I am demoing Cloud Foundry at the SD Forum Cloud Services SIG in Palo Alto. And, next week I am giving a presentation on Java and Amazon EC2 at the SD Forum Java SIG.

In the rest of March there are the presentations I blogged about previously with one addition. At CommunityOne East in New York I am giving a second presentation: Dynamic Languages: the next big thing for the JVM or an evolutionary dead end? In this presentation I am going to describe my experiences writing Cloud Tools in Groovy and then compare Groovy with Scala, which is a rather interesting statically typed language.

Decomposing Selenium Web Tests to Hide Complexity

Wednesday, 11 February 2009 9:57 A GMT-08

Decomposition is an interesting topic. In the real world, decomposition of an organism usually leads to bad smells and other unpleasantness. But in the software world, it is the absence of decomposition that causes code smells. If the responsibilities of a software system are not distributed appropriately among classes, methods and aspects then it invariably consists of large blobs of unstructured code that contains a lot of duplication. And, the software system dies prematurely.

It is usually straightforward to decompose most parts of an application, especially the domain model. But I've often found it difficult to eliminate smells from web tests that are implemented using a framework such as Selenium RC.

Here is an example of a test that was, perhaps, originally generated by the Selenium IDE and then simplified slightly by using the Umangite framework:

public class ExampleOfBadWebTests extends AbstractSeleniumTest {
   @Test
   public void testCreateProject()  {
    open("/ptrack/");
    type("j_username", "proj_mgr");
    type("j_password", "faces");
    clickAndWait("Login");
    assertTextPresent("(" + "proj_mgr" + ")");
    clickAndWait("link=Create New");
    String projectName = "XXX Project" + System.currentTimeMillis();
    type("projectDetails:nameInput", projectName);
    select("projectDetails:typeSelectOne", "label=External Desktop Application");
     …
    clickAndWait("projectDetails:save");
    assertTextPresent("Inbox - approve or reject projects");
    assertTextEquals(projectName, "inboxPage:inboxTable:2:projectName");
   
    clickAndWait("inboxPage:inboxTable:2:details");
    assertTextPresent(projectName);
    assertTextPresent("External Desktop Application");
    assertTextEquals("Sean Sullivan", "detailsPage:initiatedBy");
    ….
    assertTitle("ProjectTrack - Project details");
    clickAndWait("detailsPage:ok");
    clickAndWait("link=Logout");
    assertTextPresent("Welcome to Project Track");
   }
}

Tests like these are incredibly easy to generate using Selenium IDE but there are several problems: they are written using the very low-level Selenium API, there is potentially huge amounts of code duplication, and they consist of obscure and difficult to understand code, etc. Imagine coming back to code like this three months later and changing to reflect a new UI.

We can improve these tests by decomposing them into a series of helper methods. Here is an example of that:

public class ImprovedExampleOfTests extends AbstractSeleniumTest {

   @Test
   public void testCreateProject()  {
       login();
       
       createProject();
       assertProjectDisplayedInInbox();

        viewProjectDetails();
        assertProjectDetailsDisplayed();
   
        returnToInbox();
        logout();
   }

}


The messy details have been moved into the helper methods:

 private void createProject() {
    clickAndWait("link=Create New");
    projectName = "XXX Project" + 
                        System.currentTimeMillis();
    type("projectDetails:nameInput", projectName);
    select("projectDetails:typeSelectOne",
        "label=External Desktop Application");
    type("projectDetails:requirementsInput",
                   "Chris Richardson");
    type("projectDetails:requirementsEmailInput",
        "chris@chrisrichardson.net");
     …
    clickAndWait("projectDetails:save");
  }

These helper methods have intention revealing names making the test a lot easier to read. Code duplication has been eliminated etc. 

This approach to structuring tests isn't too bad. The tests themselves are easy to understand and change. However, I've found that the test classes themselves can get very large. And, apart from moving code that is shared between test classes into a common superclass there isn't much you can do to improve them.

Recently, however, we have successfully used a different approach to structuring tests. Instead of using what is essentially a procedural programming style we have been using object-oriented design to structure the tests. There are two big ideas here.

The first is to define a class for each screen or page in the UI and to move the code associated with that page into that class. Here is an example of a test written using this approach:

 public class DecomposedWebTest extends AbstractSeleniumTest {


    private LoginPage loginPage = new LoginPage();
    private InboxPage inboxPage = new InboxPage();
    private CreateProjectPage createProjectPage = new CreateProjectPage();
    private ProjectDetailsPage projectDetailsPage = new ProjectDetailsPage();

    @Test
    public void testCreateProject() throws InterruptedException {
        Project projectToCreate = ProjectMother.makeProjectToCreate();

        loginPage.login("proj_mgr", "faces");
        inboxPage.beginCreatingProject();
        createProjectPage.enterNewProjectInfo(projectToCreate);
   
        inboxPage.assertOnPage()
            .assertProjectDisplayed(projectToCreate)
            .viewProjectDetails();
        
        projectDetailsPage
            .assertProjectDisplayed(projectToCreate)
            .returnFromProjectDetails();
        
        inboxPage.logout();
        loginPage.assertOnPage();
    }

}

The messy helper method code has been moved into the  corresponding Page class. Its easy to tell the expected current page when reading the test code.

The second big idea is to define classes for the various page elements such as form fields, buttons, and links:

public class LoginPage extends AbstractPage {

    private TextField userNameField = new TextField("j_username");
    private TextField passwordField = new TextField("j_password");
    private Button loginButton = new Button("Login");
   
    void login(String userId, String password) {
        open("/ptrack/");
        userNameField.type(userId);
        passwordField.type(password);
        loginButton.clickAndWait();
        assertTextPresent("(" + userId + ")");
    }

    void assertOnPage() {
        assertTextPresent("Welcome to Project Track");
    }

}

One benefit of using these components is that the DOM id/selector is now only used in one place - the constructor argument  - rather than being sprinkled through the test code. If we change the UI by eliminating a component or changing the component then that will result in a compilation error in the test code. Also, although these component classes are generally simple wrappers around the Selenium RC APIs they can encapsulate more complex code that, for example, handles Dojo widgets.

By decomposing large test classes into multiple page and page component classes we have been able to eliminate quite a few smells and make the tests a lot easier to understand and maintain.

Thoughts?

Latest LinkBlogs