Sending Play Framework File Uploads to Amazon S3

UPDATE: I’ve released a S3 Play Module based on this project.

A couple of questions [1, 2] on StackOverflow.com led me to look into how we can send file uploads in a Play Framework application to Amazon S3 instead of the local disk. For applications running on Heroku this is especially important because the local disk is not persistent. Persistent disk storage makes it hard to scale apps. Instead of using the file system, it’s better to use an external service which is independent of the web tier.

While at JavaZone I sat down with Peter Hilton and Nicolas Leroux to come up with a way to handle this. It only took us 30 minutes to get something working – start to finish – including setup time. This is what is so compelling about Play Framework. I’ve built many Java web apps and it always seems like I spend too much time setting up builds, IDEs, and plumbing. With Play we were setup and working on the actual app in less than a minute. After getting everything working locally it took another minute to actually run it on the cloud with Heroku. The combination of Play Framework and Heroku is a developer’s dream for fast-paced development and deployment.

All of the code for the sample application is on github:
https://github.com/jamesward/plays3upload

The basics of what we did was this:

public static void doUpload(String comment, File attachment)
{
    AWSCredentials awsCredentials = new BasicAWSCredentials(System.getenv("AWS_ACCESS_KEY"), System.getenv("AWS_SECRET_KEY"));
    AmazonS3 s3Client = new AmazonS3Client(awsCredentials);
    s3Client.createBucket(BUCKET_NAME);
    String s3Key = UUID.randomUUID().toString();
    s3Client.putObject(BUCKET_NAME, s3Key, attachment);
    Document doc = new Document(comment, s3Key, attachment.getName());
    doc.save();
    listUploads();
}

This uses a JPA Entity to persist the metadata about the file upload (for some reason we named it ‘Document’) and a reference to the file’s key in S3. But there was a sexier way, so my co-worker Tim Kral added a new S3Blob type that could be used directly in the JPA Entity. Tim also cleaned up the configuration to make it more Play Framework friendly. So lets walk through the entire app so you can see the pieces.

The app/models/Document.java JPA Entity has three fields – the file being of type S3Blob:

package models;
 
import javax.persistence.Entity;
 
import play.db.jpa.Model;
import s3.storage.S3Blob;
 
@Entity
public class Document extends Model
{
    public String fileName;
    public S3Blob file;
    public String comment;
}

The S3Blob is now doing all of the work to talk to the Amazon S3 APIs to persist and fetch the actual file.

Configuration of S3 is done by adding a plugin to the conf/play.plugins file:

0: s3.storage.S3Plugin

The S3Plugin handles reading the AWS credentials from the conf/application.conf file, setting up the S3Client, and creating the S3 Bucket – if necessary.

In the conf/application.conf file, environment variables are mapped to the configuration parameters in the Play application:

aws.access.key=${AWS_ACCESS_KEY}
aws.secret.key=${AWS_SECRET_KEY}
s3.bucket=${S3_BUCKET}

The values could be entered into the conf file directly but I used environment variables so they would be easier to change when running on Heroku.

The Amazon AWS API must be added to the conf/dependencies.yml file:

require:
    - play
    - com.amazonaws -> aws-java-sdk 1.2.7

The sample application has a new controller in app/controllers/Files.java that can display the upload form, handle the file upload, display the list of uploads, and handle the file download:

package controllers;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;
 
import models.Document;
import play.libs.MimeTypes;
import play.mvc.Controller;
import s3.storage.S3Blob;
 
public class Files extends Controller
{
 
  public static void uploadForm()
  {
    render();
  }
 
  public static void doUpload(File file, String comment) throws FileNotFoundException
  {
    final Document doc = new Document();
    doc.fileName = file.getName();
    doc.comment = comment;
    doc.file = new S3Blob();
    doc.file.set(new FileInputStream(file), MimeTypes.getContentType(file.getName()));
 
    doc.save();
    listUploads();
  }
 
  public static void listUploads()
  {
    List<Document> docs = Document.findAll();
    render(docs);
  }
 
  public static void downloadFile(long id)
  {
    final Document doc = Document.findById(id);
    notFoundIfNull(doc);
    response.setContentTypeIfNotSet(doc.file.type());
    renderBinary(doc.file.get(), doc.fileName);
  }
 
}

The uploadForm() method just causes the app/views/Files/uploadForm.html page to be displayed.

The doUpload() method handles the file upload and creates a new Document object that stores the file in S3 and the comment in a database. After storing the file and comment it runs the listUploads() method. Of-course a database must be configured in the conf/application.conf file. For running on Heroku the database is provided and just needs to be configured with the following values:

db=${DATABASE_URL}
jpa.dialect=org.hibernate.dialect.PostgreSQLDialect
jpa.ddl=update

The listUploads() method fetches all Document objects out of the database and then displays the apps/views/files/listUploads.html page.

If a user selects a file from the list then the downloadFile() method is called which finds the file in S3 and sends it back to the client as a binary stream. An alternative to this would be to get the file directly from Amazon using either the S3 generatePresignedUrl() method or via CloudFront.

Finally in the conf/routes file, requests to “/” have been mapped to the Files.uploadForm() method:

GET     /                                       Files.uploadForm

That’s it! Now we have an easy way to persist file uploads in an external system!

Running the Play! app on Heroku

If you’d like to run this example on Heroku, here is what you need to do:

Install the heroku command line client on Linux, Mac, or Windows.

Login to Heroku via the command line:

heroku auth:login

Clone the git repo:

git clone git@github.com:jamesward/plays3upload.git

Move to the project dir:

cd plays3upload

Create the app on Heroku:

heroku create -s cedar

Set the AWS environment vars on Heroku:

heroku config:add AWS_ACCESS_KEY="YOUR_AWS_ACCESS_KEY" AWS_SECRET_KEY="YOUR_AWS_SECRET_KEY" S3_BUCKET="AN_AWS_UNIQUE_BUCKET_ID"

Upload the app to Heroku:

git push heroku master

Open the app in the browser:

heroku open

Let me know if you have any questions or problems. And thanks to Peter, Nicolas, and Tim for helping with this!

Posted in Heroku, Java, Play Framework | 24 Comments

Java and Play Framework on the Cloud at JavaZone

Next week I am speaking in Oslo at JavaZone about deploying Java and Play! Framework apps on the Cloud. I submitted the session before Heroku for Java was available so I had to obfuscate the title and description. If you are at JavaZone then I hope to see you at my “Deploying Apps on Heroku” session!

Posted in Heroku, Java, Play Framework | 2 Comments

Getting Started with Play Framework on Heroku

Last week Heroku announced that you can now run Java apps on Heroku. Today Heroku announced that you can also easily run Play Framework apps on Heroku! Here’s a quick guide to getting started with Play! on Heroku:

  1. Install the heroku command line client on Linux, Mac, or Windows.
  2. Install git and setup your SSH key
  3. Install Play! version 1.2.3
  4. Login to Heroku from the command line:

    heroku auth:login
  5. Create a new Play! app:
    play new play_hello_world
    cd play_hello_world
  6. Run the app locally to test it:
    play run --%production
  7. Create a git repo, add the files, and commit:
    git init
    git add app conf lib public test
    git commit -m init
  8. Create a new app on Heroku:
    heroku create -s cedar
  9. Push the app to Heroku:
    git push heroku master
  10. Open the app in your browser:
    heroku open

That’s it! If you want to learn more about Heroku, check out the Heroku for Java Workbook and the Heroku Dev Center. And if you are at Dreamforce 2011 then check out Felipe Oliveira’s session on “Introducing Play! Framework: Painless Java and Scala Web Applications” on Wednesday at 3:30pm.

Let me know what you think and if you have any questions.

Posted in Heroku, Play Framework | 34 Comments

Heroku Adds Java Support

Today Heroku announced that Java is now supported on the Heroku Cloud Application Platform! This is incredibly exciting news and I’m very lucky to be a Heroku for Java Developer Evangelist!

Joining salesforce.com and jumping into the the Java Cloud space holds some nostalgia for me. When I began using Java in 1997 I was working at an ISP in Denver. We did the regular web hosting thing, but when the first Java Servlet engines (like Java Web Server 1.0) came out, I created the “wantjava.com” hosting service. Things were really nasty at first. We could only run one instance of the JWS on a server so I came up with a really bad way to do “multi-tenancy”. I setup a cron job to rsync the customers’ .class files into the server’s webapp and then restart the server. Customers had to email me to get a servlet added to the web.xml file. Uggg… I feel like I need to go to confession for this. But it worked and as the Servlet containers improved we quickly migrated to a more sustainable model.

Now thirteen years later I am privileged to once again be part of Java on the Cloud. But this time around things are so much easier, better, and sexier! Heroku is a leading the way in a new generation of application deployment that is making things much better for us Java developers.

What is Heroku?

Shortly I will dive into how you can run Java on Heroku, but first, what is Heroku? From my perspective, Heroku is a Polyglot Cloud Application Platform. Heroku provides us a way to run Ruby, Node.js, Clojure, and Java applications on a managed, scalable, and multi-tenant system. Heroku also provides numerous add-ons that help us make the shift from monolithic middleware to Cloud Components. Another way to say it is:

Heroku = Polyglot + Platform as a Service (PaaS) + Cloud Components

It is very exciting to see these three things coming together! With Polyglot I can choose the right tool for the job. With PaaS I don’t have to think about managing operating systems, scalability, failover, etc. And with the Cloud Component Architecture I can keep my app thin and focused on what is unique to the problem it needs to solve. Heroku brings these models together as a cloud application platform.

Running Java Apps on Heroku

Heroku can run any Java app that runs in OpenJDK 6. Today Heroku uses Maven to create a “slug” for Java apps. That slug can then be loaded onto one or more “dynos“. You can tell a dyno to execute / start a Java app from the command line and you can also use a “Procfile” to provide a command that will auto-start for each instance of a specific dyno type. Web dynos are able to listen on a port and will receive HTTP traffic through a load balancer that is automatically setup for each app. With that background knowledge, lets dive into code!

For Dreamforce 2011, I (with the help of a few co-workers) put together a Heroku for Java Workbook. The Workbook provides detailed instructions on how to create web apps, connect to a database, setup worker processes, use the Redis to Go Heroku add-on, and use Spring Roo on Heroku. But if you are anxious to get started and don’t need as much hand-holding, here is a quick and very simple walk through of how to run Java on Heroku:

  1. Install the heroku command line client on Linux, Mac, or Windows.
  2. Install git and setup your ssh key
  3. Install Maven
  4. Login to Heroku from the command line:

    heroku auth:login
  5. Create a new project directory and move into it:

    mkdir helloherokujava
    cd helloherokujava
  6. Create a Maven build file named pom.xml containing:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>foo</groupId>
        <version>1.0-SNAPSHOT</version>
        <name>helloherokujava</name>
        <artifactId>helloherokujava</artifactId>
    </project>
  7. Create a Java source directory:

    mkdir -p src/main/java
  8. Create a new Java class in the src/main/java directory named Hello.java containing:

    public class Hello
    {
      public static void main(String[] args)
      {
        System.out.println("hello, world");
      }
    }
  9. Compile the class:

    mvn compile
  10. Run the class locally:

    java -cp target/classes Hello
  11. Create a local git repo, add the pom.xml file & src dir, and commit the files:

    git init
    git add pom.xml src
    git commit -m init
  12. Create a new app on Heroku using the Cedar stack:

    heroku create -s cedar
  13. Upload your app to Heroku:

    git push heroku master

    Heroku will create a slug for your app.

  14. Run the app on Heroku:

    heroku run "java -cp target/classes Hello"

    Heroku will start a new dyno with your slug and then run the specified command.

You just ran Java on the cloud! Obviously this is a very simple example. But I like to start new things with the simplest thing that could possibly work. Now that you have that working there is more to learn and much more power to harness!

Next Steps

Have fun and please let me know if you have any questions about Heroku.

Posted in Heroku, Java | 6 Comments

WAR-less Java Web Apps

Have you ever thought about why in Java we package up web apps into WAR files (or WAR directory structures)? It certainly is a convenient way to move an application and its dependencies from one place to another. But wouldn’t it be nice if everything could just stay in its original location and there wouldn’t be any moving of files around? Wouldn’t it also be nice if you specified your required version of Jetty or Tomcat just like you do with every other dependency? The WAR-less approach is one that is catching on as emerging Java web frameworks like Play! ditch the WAR files. With standard Java web apps we can also ditch the WAR files by simply launching an embedded Jetty or Tomcat server. Let’s give this a try and see how it goes.

For this experiment I’m going to use Maven and Jetty. This will still use the same standard source structure for a WAR file (src/main/java, src/main/webapp, etc). The major difference is that I will actually startup Jetty using a good-old static void main. This is similar to using the jetty:run goal but will allow us to have the same exact setup in development and in production. The static stuff will be in src/main/webapp, the compiled classes will be in target/classes, and the dependencies will be right were Maven downloaded them to. First, here is a little Java class (src/main/java/foo/Main.java) that sets up a Jetty server and starts it:

package foo;
 
import java.io.File;
import java.net.URL;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
 
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.*;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.webapp.WebAppContext;
 
public class Main
{
 
  public static void main(String[] args) throws Exception
  {
    String webappDirLocation = "src/main/webapp/";
 
    Server server = new Server(8080);
    WebAppContext root = new WebAppContext();
 
    root.setContextPath("/");
    root.setDescriptor(webappDirLocation + "/WEB-INF/web.xml");
    root.setResourceBase(webappDirLocation);
 
    root.setParentLoaderPriority(true);
 
    server.setHandler(root);
 
    server.start();
    server.join();
  }
}

As you can see, Main just references the webapp directory so I don’t have to copy the stuff from there to another place. Next I have a little test servlet (src/main/java/foo/HelloServlet.java):

package foo;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.http.*;
 
public class HelloServlet extends HttpServlet
{   
 
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
  {
    PrintWriter out = resp.getWriter();
    out.println("hello, world");
    out.close();
  }
}

And now the web.xml file (src/main/webapp/WEB-INF/web.xml):

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

And finally a pom.xml file that specifies Jetty as a dependency and provides an easy way to run the Main class:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.jamesward</groupId>
  <version>1.0-SNAPSHOT</version>
  <name>warless_java_web_app</name>
  <artifactId>warless_java_web_app</artifactId>
  <packaging>jar</packaging>
 
  <properties>
    <jettyVersion>7.3.1.v20110307</jettyVersion>
  </properties>
 
  <dependencies>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-server</artifactId>
      <version>${jettyVersion}</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-webapp</artifactId>
      <version>${jettyVersion}</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-servlet</artifactId>
      <version>${jettyVersion}</version>
    </dependency>
  </dependencies>
 
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.2</version>
        <configuration>
          <mainClass>foo.Main</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

And now simply run:

mvn compile exec:java

Maven compiles my Java classes into target/classes and then the exec:java goal runs the Main which finds the other WAR assets in the src/main/webapp directory. If you have been following along, make a request to http://localhost:8080/ to verify that it works (which it should).

There are two alternatives to running Jetty from Maven. You can use the Maven appassembler plugin to create start scripts containing the correct CLASSPATH references and then launch Main class using the generated scripts. Or you can use the Maven assembly or shade plugin to create a JAR containing the application and all of its dependencies.

Here is an example section of a pom.xml file for using the appassembler plugin:

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>appassembler-maven-plugin</artifactId>
    <version>1.1.1</version>
    <configuration>
      <assembleDirectory>target</assembleDirectory> 
      <generateRepository>false</generateRepository>
      <programs>
        <program>
          <mainClass>foo.Main</mainClass>
          <name>main</name>
        </program>
      </programs>
    </configuration>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>assemble</goal>
        </goals>
      </execution>          
    </executions>
  </plugin>

To generate the start scripts simply run:

mvn install

Then to run the script set the REPO environment variable to your Maven repository:

export REPO=~/.m2/repository

And then simply run the script:

sh target/bin/main

All of the code for this example is on github.com:
https://github.com/jamesward/warless_java_web_apps

To make all of this even easier, Jetty has a Maven archetype for generating everything for you. To create a new project containing this setup run:

mvn archetype:generate -DarchetypeGroupId=org.mortbay.jetty.archetype -DarchetypeArtifactId=jetty-archetype-assembler -DarchetypeVersion=7.5.0-SNAPSHOT

And now you are ready to build a WAR-less Java web app!

This setup is really the bare minimum required to handle web resource and servlet requests you will need to do a little more work if you want to add JSP support. Find out more about this in the Jetty documentation.

So… What do you think about Java Web apps without WAR files & WAR packaging? I’d love to hear your thoughts!

Posted in Java | 6 Comments

Dreamforce 2011

I’m very excited to be presenting at Dreamforce (salesforce.com’s anual conference) this year! On Thursday, September 1, from 1:15 pm to 2:15 pm I will be presenting:

Developing Java Cloud Apps
The cloud makes it easy to deploy highly scalable apps in an instant. This session will walk you through the steps to build your first Java app for the cloud. You’ll also learn best practices for building mission-critical and horizontally scalable Java cloud apps.

Then on Friday, September 2, from 10:00 am to 11:00 am I will be hosting a panel discussion:

Fireside Chat: Java on the Cloud
Come join the Java on the cloud product managers, architects, and experts for a casual, unscripted chat to find out how Java developers can best take advantage of the cloud. The session will be a mix of preselected and audience-provided questions. So bring all your tough, interesting, and quirky questions to this Fireside Chat.

I hope to see you there!

Posted in Cloud, Conferences, Java | Leave a comment

Setup Play Framework with Scala in IntelliJ

Yesterday at the Programming Summer Camp a group of us were working together to learn the Play Framework. Once we were able to get the basics working we wanted to get everything working in IntelliJ IDEA. Due to a lack of good documentation on the subject things did not go smoothly until we figured out the right “magical incantations”. We did eventually get it working so I wanted to document the steps we took.

  1. Add Scala support to Play:
    play install scala
  2. Create a new Play project with Scala support:
    play new foo --with scala
  3. Have Play create an IntelliJ Module Descriptor:
    play idealize foo
  4. Run the app:
    play run foo
  5. Access the app in a browser to generate some source files we will use later:
    http://localhost:9000
  6. Shutdown the Play server.
  7. Currently the Play Scala Module (version 0.9.1) only supports Scala 2.8.1 so download and extract that version.
  8. Create a new project (from scratch) in IntelliJ. The location should be the same as the directory where the Play project was created. Un-check the “Create module” option.
  9. In the Project Structure window, with “Modules” selected, click the “+” button to add a new module to the project.
  10. Select the “Import existing module” option and then point it to the generated .iml file.
  11. With the module now selected, select the content root block for the module (mine is /home/jamesw/projects/foo). Then select the “tmp/generated” directory in the tree on the right and press the “Sources” button. The HTML template pages are converted to .scala source files by Play and we need these source files to be included in the project along with the regular source files in the app directory.
  12. Select “Global Libraries” in the Platform Settings on the left and add a new Java Library named “scala-compiler-2.8.1″. Then press the “Attach Classes…” button and navigate to the “lib” directory in your Scala 2.8.1 directory. Then select the “scala-compiler.jar” and “scala-library.jar” files.
  13. Add another Global Library named “scala-library-2.8.1″ containing the “scala-dbc.jar”, “scala-library.jar”, and “scala-swing.jar” files.
  14. Press the “Apply” button to save the Global Libraries configuration.
  15. Select “Modules” and then the “Dependencies” tab. Press the “Add…” button and select “Library” to add a new library to the module. Select “scala-library-2.8.1″ and then press the “Add Selected” button to add it to the Dependencies.
  16. Select the “Scala” Facet in the module and set the Compiler library to the “scala-compiler-2.8.1″ option.
  17. Save the Project Structure by pressing the “Ok” button. Make sure the project now builds without any errors.
  18. To run the Play server from IntelliJ a new Run Configuration must be configured. To create a new Run Configuration select “Run” from the main IntelliJ menu and then select “Edit Configurations”.
  19. Press the “+” button and select “Application” from the list of Run Configuration types.
  20. Set the name to “Play Server”.
  21. Set the Main class to “play.server.Server”.
  22. Set the VM Parameters to:
    -Dapplication.path="."
  23. De-select the “Make” option in the “Before Launch” section.
  24. Press the “Ok” button to save the configuration.
  25. Run the Play Server by selecting “Run” from the “Run” IntelliJ menu and verify that the application still works by opening the application in a browser.

It is so much easier to figure this stuff out with a group of people. That is just one of the many reasons why the Programming Summer Camp is a great event!

Let me know if you have any questions or problems.

Posted in Play Framework, Scala | 28 Comments

Architectural Evolution: From Middleware to The Cloud

You’ve heard it said that “all things old are new again.” That statement can certainly be applied to the current Cloud hype. But each time the old becomes new it gets a bit better because of what was learned the last time around. If we look back ten years at enterprise application development in Java things were quite different than they are today. EJB was “the way” to build scalable systems from a vast abundance of components. But things didn’t work out as well as the vendors planned.

EJB Component Architecture

I remember back in the early days of enterprise Java everyone was talking about “Components.” Application complexity would be greatly reduced because there would be components for everything! Need to connect your app to Exchange? Well, there’s a component for that. Does your app need to send email? No problem, there are twenty components for that! Component marketplaces flourished with VC funding galore.

The official way to build reusable Java components became standardized as Enterprise Java Beans (EJB). These “beans” could be accessed either locally or remotely! Vendors led us to believe this was the panacea of Lego-style application development. Just grab pieces from every-which place and hook them together. Hooking the components together required a heavyweight “Middleware” server. Here is what Monolithic Middleware with EJBs looks like:

But the EJB Component Architecture didn’t work. Billions of dollars were spent on components and the middleware to tie them all together. And now I bet you can’t find a single person that doesn’t regret going that route. Why? Three primary reasons…

  1. The programming model was too hard. The EJB programming model consisted of too much boilerplate code (“solved” through code-gen tools like xdoclet). EJB’s also required configuration which was often middleware server-specific. The EJB Component Architecture creates too many layers of indirection (Core J2EE Patterns anyone?).
  2. Scalability was too hard. EJBs can either run inside your container (using what is called a “Local Interface”) or somewhere else (a “Remote Interface”). Using Local Interfaces is fast but causes middleware to run into memory limits and scaling bloated app servers is challenging. Using Remote Interfaces leads to massive serialization and routing overhead and whatever is on the remote end of the wire is still a pain to scale.
  3. Deployment was too hard. Remember the days when starting up an app server / middleware container took minutes not seconds?

If you need further proof that the middleware model didn’t work then just try to name one place you can still go to buy an EJB component today. Obviously we needed another way to compose the parts of an application.

POJO Component Architecture

SpringSource deserves a lot of credit for pulling us out of the EJB muck. They created a model where the application pieces are Plain Old Java Objects (POJOs) injected into an application. This led to better testability, much easier deployment, and a much better programming model. Essentially the revolution of Spring was to make all those app pieces injectable dependencies. This was a huge step forward. But there are still some limitations with this model that are currently being addressed by the next revolution. The three primary challenges with the POJO Component Architecture are:

  1. Isolation is too hard. It is now very easy to throw a bunch of components together into a single Web application ARchive (WAR). But at some point all of these pieces being stacked on top of each other make our application brittle and difficult to piece together. What do you do when the version of Hibernate you want to use requires a different version of an Apache Commons library than the version of XFire that you want to use? Or when two libraries that your app needs actually require conflicting dependencies. Sometimes isolating the pieces of an application is actually simpler than injecting them. And unfortunately with POJOs you may not be able to easily switch from using a “Local Interface” to an external “Remote Interface” like you can with EJBs.
  2. Polyglot is too hard. The POJO components we use today in our systems are not inherently supportive of a Polyglot world where different parts of a system may be built using different technologies. Suppose your system has a rules engine and you want to access it from a Java-based application and a Ruby-based application. Today the only way to do that is to proxy that component and expose it through an easily serialization protocol (likely XML or JSON over HTTP). This will likely add unnecessary complexity to your system. When the high-level functional pieces of a system are technology-specific the entire system may be forced to use that technology or those pieces may exist multiple times to support the Polyglot nature of today’s systems.
  3. Scaling is still too hard. As we continue to stack more pieces on top of each other it becomes harder to stick with simple, lightweight share-nothing architectures where each piece is individually horizontally scalable.

Cloud Component Architecture

The emerging solution to the challenges we have faced with the EJB and POJO Component Architectures is the Cloud Component Architecture. Instead of bundling components for things like search indexing, distributed caching, SMTP, and NoSQL data storage into your application those high level functions can instead be used as Cloud Components. There are already numerous vendors providing “Component as a Service” products like MongoDB, Redis, CouchDB, Lucene Search, SMTP, and Memcache.

SMTP / outbound email is a simple example where the Cloud Component Architecture makes a lot of sense. With the EJB and POJO Component Architectures I’d find a SMTP component that simply sends email. Then configure my server to be able to send emails that aren’t considered spam. I’d also need to deal with constant blacklisting challenges and a larger management surface. Or in a Cloud Component Architecture I could simply sign-up with one of the SMTP as a Service providers like AuthSMTP or SendGrid and then just use the Component as a Service.

Here is what the new Cloud Component Architecture for application composition looks like:

The top six benefits of the Cloud Component Architecture are:

  1. Simple scalability. By making each functional piece of an application an independent and lightweight service they can each be horizontally scaled without impacting the overall application architecture or configuration. If you chose to use a vendor’s Component as a Service then they will handle the scalability of those pieces. Then you only need to scale a very thin web layer. Composing Cloud Components also makes it easier to stick with a share-nothing architecture that is much easier to scale than the traditional architectures.
  2. Rapid composition. Cloud Components are flourishing! Most of the basic building blocks that applications need are now provided “as a Service” by vendors who maintain and enhance them. This is a much more erosion-resistant way to assemble applications when compared to the typical abandon-ware which is prevalent with many Java components. Many of the emerging Cloud Components also provide client libraries for multiple platforms and RESTful APIs to support easy composition in Polyglot systems.
  3. Reduced management surface. With Cloud Components you can reduce the number of pieces you must manage down to only the stuff that is unique to your app. Each Cloud Component you add doesn’t enlarge the management surface like it does in typical component models where you own the implementation of the component.
  4. Simple Deployment. One of the biggest benefits of using the Cloud is the ease of deployment. Partitioning the functional pieces of an application makes it thinner and easier to deploy. With Cloud Components you can also setup development and staging instances that make it easy to simulate the production environment. Then moving from one environment to another is simply a matter of configuration.
  5. Better Security. In most application architectures today there is one layer of security. This would be like a bank without a vault. There are a few ways into the bank that are wrapped with security (doors with locks) but as soon as someone has found a way in, they have access to everything. With Cloud Components security can be more easily distributed to provide multiple layers of security.
  6. Manageable costs. With Cloud Components your costs can scale with your usage. This means it’s easy to get started and grow rather than make large up-front investments.

The Cloud Component Architecture may seem similar in ways to the old EJB and POJO Component Architectures because it is similar! The wheel has not been reinvented, just improved. The dream of Lego-style application assembly is now being realized because we’ve come full circle on some old ideas from twenty years ago (CORBA anyone?). This time around those ideas are reality thanks to the evolution of many independent pieces like REST, Polyglot, and the Share-Nothing pattern. Cloud Components are the foundation of a new era of application development. My only question is… How long before we see the UDDI idea again? ;)

Posted in Cloud, Java | 9 Comments

Programming Summer Camp 2011

Over the past few years I’ve attended a bunch of geek/coder events in the Colorado Mountains. It always surprises me how much I can learn by getting away, being around some really smart people, and writing code with them. So I’m incredibly excited to be attending The Programming Summer Camp 2011 this summer in Crested Butte, Colorado!

At the summer camp you can choose which campsite to hangout in. Or if you want, you can create your own campsite! I’ll probably spend most of my time in the Scala campsite. But I look forward to mingling in some of the other campsites as well.

It’s like I’m a kid again – getting all excited about going to camp! But I really hope you all can join me July 25 – 29 in Crested Butte, Colorado for The Programming Summer Camp 2011!

Posted in Conferences | Leave a comment