Ph: 34069381

Webapp Runner – Apache Tomcat as a Dependency

John Simone, a fellow co-worker at Heroku, has created webapp-runner which provides an easy way to specify Tomcat as a dependency of your app and launch Tomcat. This is useful for making it simple to test your app locally but it also helps to avoid issues stemming from differences in runtime environments.

Here is how to use it from a Maven pom.xml build:

<?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>org.example</groupId>
    <artifactId>hellojavawebapprunner</artifactId>
    <name>hellojavawebapprunner</name>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
 
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.github.jsimone</groupId>
            <artifactId>webapp-runner</artifactId>
            <version>7.0.22</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                    <webappDirectory>${project.build.directory}/${project.artifactId}</webappDirectory>
                    <warName>${project.artifactId}</warName>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals><goal>copy-dependencies</goal></goals>
                        <configuration>
                            <includeArtifactIds>webapp-runner</includeArtifactIds>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Then just run the Maven build:

mvn package

And start up Tomcat using webapp-runner pointing to the exploded war:

java -jar target/dependency/webapp-runner-7.0.22.jar target/hellojavawebapprunner

Or you can point it to a war file:

java -jar target/dependency/webapp-runner-7.0.22.jar target/hellojavawebapprunner.war

Since this method still uses war packaging you can do the usual web app deployment in Eclipse or IntelliJ. But that means deploying to a different runtime than what is specified as a dependency. Since one goal of using the webapp-runner is runtime consistency it is better to launch the webapp-runner for local testing. To do that just use the “webapp.runner.launch.Main” class and give it “src/main/webapp” as an argument. Eclipse will include the webapp-runner jar in the launch classpath even though the scope is “provided”. In IntelliJ you need to either manually add the libraries to the runtime classpath or change the scope to “compile” (the default). But this has a side effect of copying the jars into the WEB-INF/lib directory. Maybe someone else knows of a better solution.

I’ve posted a simple example project on GitHub that uses the webapp-runner. Also checkout the webapp-runner project on GitHub for more details on how to use it. If you’d like to try this out on Heroku then you can easily deploy a copy using the java.herokuapp.com app that I created.

Let me know if you have any questions or comments. Thanks!

Posted in Java, Tomcat | Leave a comment

Video: Java, Play Framework & Scala Apps on Heroku

If you haven’t been able to make it to one of my Java User Group talks about Heroku but you want to see the presentation, then you are in luck! The Portland JUG recorded my talk on Running Java, Play Framework, and Scala Apps on the Cloud with Heroku. Check it out and let me know if you have any questions or comments. Thanks!
[ http://player.vimeo.com/video/34069381 ]

Posted in Heroku, Java, Play Framework, Scala | Leave a comment

Video: Spring Roo and Grails Apps on the Cloud

At SpringOne 2GX I did a presentation about running Spring Roo (really Spring anything) and Grails apps on the cloud with Heroku. A video recording of my session has been posted on InfoQ.

If you want to try out Spring Roo or Grails on Heroku then one way is to deploy a copy of one of the demos I showed. I’ve created a little app that makes that easy. Just go to java.herokuapp.com and select a demo then enter your email address (your Heroku username) and click Go! A copy of the demo will be deployed for you on Heroku and then you will see instructions on how to get started with it. Give it a try and let me know what you think.

Posted in Heroku, Java, Spring | Leave a comment

Deploy Containerless Tapestry Apps on Heroku

Recently I spent some time with Howard Lewis Ship, creator of the Apache Tapestry web framework. Howard is a technical rock star so it was really fun to sit down with him and hack on some code. Our goal was to make it easy for people to run their Tapestry apps on the cloud with Heroku. You can run anything on Heroku so there are a variety of ways to run Tapestry apps on Heroku. We wanted to put together something that helps Tapestry users run their apps in the most optimal way. What we came up with is available in Howard’s tapx-heroku package on GitHub. Lets walk through what it does.

The JettyMain class provides a simple way to start a Java web app using an embedded Jetty server. This “Containerless” method has these advantages over the traditional container deployment model:

The HTTP handling library (Jetty in this case) is a dependency of my application. This alleviates pain caused by differences in developer and production deployment environments. My app is just a plain Java library so it can be packaged as a regular JAR file and used as a dependency itself. The application starts up super fast. I have a way to setup the application (like the session storage provider) in code instead of having to do it in XML. Development cycles are faster as a result of lightweight packaging and deployment. With IntelliJ or JRebel class hot-swapping can make those cycles even shorter. (This is also an out-of-the-box feature with Tapestry.)

To use JettyMain with your Tapestry app, we just need to update the Maven build (pom.xml) file. You can do this with an existing app or start from scratch using the Tapestry Maven Archetype. Here is a simple pom.xml file:

<?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>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    <name>herokuapp</name>
    <artifactId>herokuapp</artifactId>
    <packaging>jar</packaging>
 
    <repositories>
        <repository>
            <id>howardlewisship</id>
            <url>http://howardlewisship.com/snapshot-repository</url>
        </repository>
    </repositories>
 
    <dependencies>
        <dependency>
            <groupId>org.apache.tapestry</groupId>
            <artifactId>tapestry-core</artifactId>
            <version>5.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.howardlewisship</groupId>
            <artifactId>tapx-heroku</artifactId>
            <version>1.2-SNAPSHOT</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.4</version>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals><goal>copy-dependencies</goal></goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
 
</project>

This specifies Tapestry and the tapx-heroku libraries as dependencies. The tapx-heroku library will automatically pull in the Jetty dependencies. The maven-dependency-plugin will copy the runtime dependencies from the local Maven cache to the target/dependency directory so that we can easily setup the application’s runtime classpath.

To build the app locally just run:

mvn package

To launch the application run:

java -cp target/dependency/*:target/classes com.howardlewisship.tapx.heroku.JettyMain

That’s it! Tapestry, tapx-heroku (JettyMain), Jetty, your application classes, and the rest of the required dependencies are all loaded into the JVM and the web server is started. Super simple stuff!

The JettyMain app has a few optional command line arguments for overriding the defaults. You can see those by running:

java -cp target/dependency/*:target/classes com.howardlewisship.tapx.heroku.JettyMain -help

If you want to try out a simple app that already has this setup then I have one on GitHub that you can copy locally by doing a git clone:

git clone https://github.com/jamesward/hellotapestry.git

Now lets run this on the cloud with Heroku. To follow along you need to install the Heroku toolbelt and signup for a Heroku.com account. Don’t worry, you won’t need to enter a credit card to give this a try because Heroku gives you 750 free dyno hours per application, per month. (Wondering what a “dyno” is? Check out: How Heroku Works)

We need to tell Heroku what process on the system to run in order to start up the web application. To do this we need a file named Procfile (with a capital ‘P’) in the project’s root directory. The contents of that file should be:

web:   java -cp target/dependency/*:target/classes com.howardlewisship.tapx.heroku.JettyMain

In this case we will upload the source up to Heroku where it will run the Maven build. This is the standard Heroku deployment mechanism because it makes the deployment process super fast and makes sure that there are no discrepancies between the different environments. The dependencies are downloaded on the cloud (i.e. very quickly) instead of doing the typical lengthy package and upload process. But you can also upload binary assets if you prefer. Heroku uses git for file upload so if you don’t already have the project files in a git repo then you need to create the repo, add the files, and commit them:

git init
git add src pom.xml Procfile
git commit -m init

Now we can provision an application on Heroku by logging in from the Heroku CLI and creating an application on the “cedar” stack:

heroku login
heroku create -s cedar

The application can now be uploaded using git:

git push heroku master

When the upload has finished Heroku will run the Maven build, deploy the compiled application onto a dyno, and start the web process defined in the Procfile. Test out the application in your browser by running:

heroku open

Great! You now have a Tapestry app running on the cloud! But there is one other cool thing the JettyMain does for us. Java web applications often use in-memory session state which does not work well with the server affinity model that is necessary for scalable cloud deployments. Out-of-the-box Tapestry uses the session state very minimally but it’s possible that your application uses it more heavily. Heroku dynos are intended to be stateless so they can be managed, scaled, and configured without disrupting active users. This means that the session state needs to be in an external store. Luckily Jetty makes it easy to transparently move session state to an external MongoDB system (see my Using MongoDB for a Java Web App’s HttpSession post for more details).

The JettyMain app has this functionality built in as long as you either set the mongo-url application parameter or have set either a MONGOHQ_URL or MONGOLAB_URL environment variable. On Heroku it’s very easy to create a MongoDB system for your application to use. The Heroku add-ons provide numerous Cloud Services to Heroku apps, including two MongoDB providers: MongoLab and MongoHQ. Both have free tiers, so pick one and then add it by running either of these commands:

heroku addons:add mongolab
heroku addons:add mongohq

This will automatically provision the MongoDB system, set the connection information in the expected environment variable, and then restart your dyno(s) so that they pickup the new configuration. The JettyMain will now switch Jetty’s session storage provider to the MongoDB system instead of using in-memory storage. Cool stuff!

Let me know if you have any questions and thanks Howard for putting this together!

Posted in Heroku, Java, Tapestry | 6 Comments

Run Grails on the Cloud with Heroku

Support for Grails on Heroku was recently announced and I’d like to walk you through the steps to create a simple Grails app and then deploy it on the cloud with Heroku. Before you get started install Grails 2.0.0, install the Heroku toolbelt, install git, and signup for a Heroku.com account. Don’t worry, you won’t need to enter a credit card to give this a try because Heroku gives you 750 free dyno hours per application, per month. (Wondering what a “dyno” is? Check out: How Heroku Works) Let’s get started.

Step 1) Create the app:

grails create-app grailbars

You’ll need to do the rest of this from inside the newly created “grailbars” directory:

cd grailbars

Step 2) Create a new domain object:

grails create-domain-class com.jamesward.grailbars.Bar

Step 3) Edit the grails-app/domain/com/jamesward/grailbars/Bar.groovy file so it looks like:

package com.jamesward.grailbars
 
class Bar {
    String name
}

Step 4) Generate the controllers and views for the Bar model:

grails generate-all com.jamesward.grailbars.Bar

Step 5) Run the app locally to test it out:

grails run-app

Now open it in your browser: http://localhost:8080/grailbars

Step 6) Heroku provides a free Postgres database that we want our application to use. The easiest way to do that is using the Heroku Grails Plugin. Install the “heroku” and the “cloud-support” plugins:

grails install-plugin heroku
grails install-plugin cloud-support

Then edit the grails-app/conf/BuildConfig.groovy file and add the Postgres JDBC driver as a dependency by adding the following to the “dependencies” section:

    runtime 'postgresql:postgresql:9.1-901-1.jdbc4'

Step 7) Setup a git repository for the project which will be used for transferring the files to Heroku:

grails integrate-with --git
git init
git add application.properties grails-app test web-app
git commit -m init

Step 8) Login with the Heroku CLI:

heroku login

Step 9) Ceate a new application using the “cedar” stack:

heroku create -s cedar

Step 10) Upload your application to Heroku:

git push heroku master

Now open the application running on Heroku in your browser (the URL was in the “heroku create” and “git push” output). Verify that it works. Awesome! You just built a Grails app and deployed it on the Cloud with Heroku! For more details on using Grails on Heroku, visit the Heroku Dev Center and checkout the Heroku Grails Plugin documentation. Let me know if you have any questions. Thanks!

Posted in Grails, Heroku | 7 Comments

Next Gen Web Apps with Scala, BlueEyes, and MongoDB

Web application architecture is in the midst of a big paradigm shift. Since the inception of the web we’ve been treating the browser like a thin client. Apps just dump markup to the browser which is then rendered. Every interaction requires a request back to the server which then returns more logic-less markup to the browser. In this model our web applications are server applications. There are certainly advantages to this model – especially when the markup consumers don’t have the capabilities to do anything more (or have inconsistent capabilities).

Web browser modernization has paved the way to move from the old “browser as a thin client” model to more of a Client/Server model where the client-side of the application actually runs in the browser. There are a lot of names for this new model, Ajax being a step along the way, and perhaps HTML5 being the full realization of Client/Server web apps.

There are hundreds of new libraries, tools, programming languages, and services that support the creation of these next generation web (and mobile) apps. One thing that is certainly lacking is one cohesive, end-to-end solution. I have no doubt that we will be seeing those crop up soon, but in the mean time lets pick a few libraries and build a couple simple apps to get a better understanding of what this new model looks like.

I’ve decided to try this with a stack consisting of Scala for my back-end code, BlueEyes for handling data access and serialization with transport over HTTP, MongoDB for data storage, and JavaScript with jQuery for the client-side. I’m going to keep this very simple and not pull in anything else. In future articles I’ll expand on this foundation.

So lets dive into some code. All of the code is on GitHub. If you want to get a local copy just do:

git clone git://github.com/jamesward/helloblueeyes.git

This project uses the Scala Build Tool (SBT) for downloading dependencies, compiling, and packaging. Follow the SBT setup instructions if you want to be able to compile the code on your machine. If you want to use IntelliJ or Eclipse then run one of the following commands:

sbt gen-idea
sbt eclipse

Lets start with some BlueEyes basics. BlueEyes is a lightweight web framework built on Netty (a really high performance, NIO-based HTTP library). BlueEyes makes it easy to define a tree of HTTP request handling patterns. I chose BlueEyes because it’s really lightweight and utilizes some nice features of the Scala language to make the code very concise. It’s kinda like a DSL for HTTP request handling.

To get started with BlueEyes we first need to create an AppServer that provides a way to start the server and a place to plug services into. Here is the code for the AppServer:

package net.interdoodle.example
 
object AppServer extends EnvBlueEyesServer with HelloHtmlServices with HelloJsonServices with HelloStartupShutdownServices with HelloMongoServices

My AppServer is an object which means it’s a singleton (that makes sense because I can’t have more than one of these in a single instance). The AppServer extends EnvBlueEyesServer which is a wrapper around the base BlueEyesServer that provides a way to get the HTTP port via an environment variable (this is necessary for running on Heroku – which we will get to later). The AppServer composes in a bunch of Services that actually setup HTTP request pattern trees.

Starting with the simplest one, HelloHtmlServices we have:

trait HelloHtmlServices extends BlueEyesServiceBuilder with BijectionsChunkString {
  val helloHtml = service("helloHtml", "0.1") { context =>
      request {
        path("/") {
          produce(text/html) {
            get { request =>
              val content = <html>
                <body>Hello, world!</body>
              </html>
              val response = HttpResponse(content = Some(content.buildString(true)))
              Future.sync(response)
          }
        }
      }
    }
  }
}

Using the BlueEyesServiceBuilder the HelloHtmlServices trait creates a service that consists of a big pattern match that goes something like this: For a request to path “/”, produce an HTML response when there is a HTTP GET request. Notice that the response is actually wrapped in a Future. This is an important part of the next generation web app architecture. Because the underlying HTTP server is NIO-based (non-blocking), the actual HTTP handling threads can be very efficiently managed so that a thread is only in use when actual IO is happening. BlueEyes supports this by using Future wrapped responses, allowing the HTTP thread to be unblocked by back-end processing.

If you want to try this out locally run the following to compile the app and create a Unix script that makes it easy to start the AppServer:

sbt stage

Now start the AppServer process:

target/start net.interdoodle.example.AppServer

Verify that HelloHtmlServices is working by opening the following URL in your browser:
http://localhost:8080/

Now lets walk through a few steps to deploy this application on the cloud with Heroku.
Step 1) Sign up for a Heroku account
Step 2) Install the Heroku Toolbelt
Step 3) Login to Heroku from the command line:

heroku login

Step 4) Create a new application on Heroku using the Cedar stack:

heroku create -s cedar

Step 5) Deploy the app on Heroku:

git push heroku master

Step 6) Verify that the app works in your browser:

heroku open

Great! We have an app built with Scala and BlueEyes running on the cloud. Now for the next piece of the architecture. The UI of the application will be written in JavaScript and will run on the client-side. But we need to have a way to transfer data between the client and the server. JSON has become the regular way to do this because it is parsed easily and quickly on the client. So a BlueEyes service will generate some JSON data that can then be consumed by a JavaScript application running on the client. But how do we get that JavaScript application running on the client? This is the next piece of the architecture.

Ideally the JSON services are served separately from the client-side of the application (where the client-side includes all HTML, JavaScript, CSS, images, and other static assets). It is also ideal to serve the client-side from a Content Delivery Network (CDN) so that it’s edge cached and loads super fast. Dynamic assets (the JSON services) can’t be edge cached so there is a logical (and functional) separation between the client-side and the server-side. But there is a problem with this approach.

The CDN and the JSON services hosts each have different DNS names and browsers don’t allow cross-origin requests (actually they don’t allow access to the responses). There are a few different ways to deal with this (JSONP, iframe hackery, etc) but the approach I’m taking is simple. The JSON services server will serve an entry point / thin shim web page. That shim then loads the rest of the client-side from the CDN and since the origin of the web page is the same as the JSON services, there is no need to make a cross-origin request. (Side note: There is a new way to do cross-origin requests cleanly and natively in the browser, but it’s not ubiquitously supported yet.)

Here is HelloJsonServices that illustrates these patterns:

trait HelloJsonServices extends BlueEyesServiceBuilder with BijectionsChunkJson with BijectionsChunkString {
  val helloJson:HttpService[ByteChunk] = service("helloJson", "0.1") { context:HttpServiceContext =>
    request {
      path("/json") {
        contentType(application/json) {
          get { request: HttpRequest[JValue] =>
            val jstring = JString("Hello World!")
            val jfield = JField("result", jstring)
            val jobject = JObject(jfield :: Nil)
            val response = HttpResponse[JValue](content = Some(jobject))
            Future.sync(response)
          }
        } ~
        produce(text/html) {
          get { request: HttpRequest[ByteChunk] =>
            val contentUrl = System.getenv("CONTENT_URL")
 
            val content = <html xmlns="http://www.w3.org/1999/xhtml">
              <head>
                <script type="text/javascript" src={contentUrl + "jquery-1.7.min.js"}></script>
                <script type="text/javascript" src={contentUrl + "hello_json.js"}></script>
              </head>
              <body>
              </body>
            </html>
            Future.sync(HttpResponse[String](content = Some(content.buildString(true))))
          }
        }
      }
    }
  }
}

This service handles requests to “/json” and if the requested content type is JSON then a simple JSON object is returned. If the requested content is HTML then the shim web page is returned. Inside the shim web page an environment variable, CONTENT_URL, is used to specify the URLs to load the JavaScript for the application.

The first JavaScript is the minified jQuery library. This abstracts some browser differences, makes doing the JSON request and modifying the webpage very simple. Here is the main client application hello_json.js:

$(function() {
    $.ajax("/json", {
        contentType: "application/json",
        success: function(data) {
            $("body").append(data.result);
        }
    });
});

This application has a function handler for when the page has loaded. That function makes an ajax request to “/json” with the “application/json” content type. Then on a successful response it just appends the result into the web page.

To run this locally first set the CONTENT_URL environment variable to the CDN where I’ve put the JavaScript files:

export CONTENT_URL=http://cdn-helloblueeyes.interdoodle.net/

Now start (or restart) the server and open:
http://localhost:8080/json

To test the JSON service locally run:

curl --header "Content-Type:application/json" http://localhost:8080/json

You can also use a local static file server for testing, just run net.interdoodle.example.httpstaticfileserver.HttpStaticFileServer and set CONTENT_URL accordingly.

If you want to try this on Heroku then set CONTENT_URL for your application:

heroku config:add CONTENT_URL=http://cdn-helloblueeyes.interdoodle.net/

This will set the environment variable and restart the application. Then navigate to the your Heroku application’s “/json” URL in your browser. Now both the server-side and client-side are cloudified!

Side Note: I’m using Amazon CloudFront as the CDN for this example. But any CDN would work fine. There are various ways to upload files to Amazon CloudFront (actually they get uploaded to Amazon S3) but one thing I’m looking into is a SBT plugin that will do this.

Now lets add some simple data access into the mix. I’ve chosen MongoDB because it has native support for JSON and we can take advantage of Hammersmith – a non-blocking MongoDB driver. In this example I’m not using Hammersmith since support for it hasn’t been officially added to BlueEyes (but at least there is the opportunity to easily switch to Hammersmith in the future).

Here is the code for HelloMongoServices:

trait HelloMongoServices extends BlueEyesServiceBuilder with MongoQueryBuilder with BijectionsChunkJson with BijectionsChunkString {
 
  val helloMongo = service("helloMongo", "0.1") {
    logging { log => context =>
      startup {
        // use MONGOLAB_URI in form: mongodb://username:password@host:port/database
        val mongolabUri = Properties.envOrElse("MONGOLAB_URI", "mongodb://127.0.0.1:27017/hello")
        val mongoURI = new MongoURI(mongolabUri)
 
        HelloConfig(new EnvMongo(mongoURI, context.config.configMap("mongo"))).future
      } ->
      request { helloConfig: HelloConfig =>
        path("/mongo") {
          contentType(application/json) {
            get { request: HttpRequest[JValue] =>
              helloConfig.database(selectAll.from("bars")) map { records =>
                HttpResponse[JValue](content = Some(JArray(records.toList)))
              }
            }
          } ~
          contentType(application/json) {
            post { request: HttpRequest[JValue] =>
              request.content map { jv: JValue =>
                helloConfig.database(insert(jv --> classOf[JObject]).into("bars"))
                Future.sync(HttpResponse[JValue](content = request.content))
              } getOrElse {
                Future.sync(HttpResponse[JValue](status = HttpStatus(BadRequest)))
              }
            }
          } ~
          produce(text/html) {
            get { request: HttpRequest[ByteChunk] =>
              val contentUrl = System.getenv("CONTENT_URL")
 
              val content = <html xmlns="http://www.w3.org/1999/xhtml">
                              <head>
                                <script type="text/javascript" src={contentUrl + "jquery-1.7.min.js"}></script>
                                <script type="text/javascript" src={contentUrl + "hello_mongo.js"}></script>
                              </head>
                              <body>
                              </body>
                            </html>
              Future.sync(HttpResponse[String](content = Some(content.buildString(true))))
            }
          }
        }
      } ->
      shutdown { helloConfig: HelloConfig =>
        Future.sync(())
      }
    }
  }
}

This service has a startup hook that creates a MongoDB connection based on the MONGOLAB_URI environment variable or a default value. Then there are three request handlers for the “/mongo” path. The first handles JSON HTTP GET requests by fetching some data from MongoDB and returning it. A JSON HTTP POST handler inserts the JSON that was sent into MongoDB. Then there is a HTML HTTP GET request handler that returns the web page shim that loads the JavaScript from the CDN.

Here is the client-side of the application hello_mongo.js:

$(function() {
 
    $("body").append('<h4>Bars:</h4>');
    $("body").append('<ul id="bars"></ul>');
    $("body").append('<input id="bar"/>');
    $("body").append('<button id="submit">GO!</button>');
 
 
    $("#submit").click(addbar);
    $("#bar").keyup(function(key) {
        if (key.which == 13) {
            addbar();
        }
    });
 
    loadbars();
 
});
 
function loadbars() {
    $.ajax("/mongo", {
        contentType: "application/json",
        success: function(data) {
            $("#bars").children().remove();
            $.each(data, function(index, item) {
                $("#bars").append("<li>" + item.name + "</li>");
            });
        }
    });
}
 
function addbar() {
    $.ajax({
        url: "/mongo",
        type: 'post',
        dataType: 'json',
        success: loadbars,
        data: '{"name": "' + $("#bar").val() + '"}',
        contentType: 'application/json'
    });
}

This JavaScript application starts by adding some elements to the page for displaying and entering “bars”. The loadbars() function makes a ajax GET request to the JSON service and then appends the result into the element on the page with the id of bars. The addbar() method makes a POST request to the JSON service, passing serialized JSON containing the name of the “bar” to the JSON service, then on success it calls loadbars().

If you want to run this locally then you will need a MongoDB server setup and running locally. Make sure CONTENT_URL is set correctly and if your MongoDB settings differ from the default, then set the MONGOLAB_URI environment variable. Start the AppServer process and then open:
http://localhost:8080/mongo

You should be able to add new “bars” and see them listed.

To run on Heroku you will need to add the MongoLab add-on. When the MongoLab add-on is added the MONGOLAB_URI environment variable on your Heroku application will be automatically set with the connection information for the newly provisioned MongoDB system. To add the MongoLab add-on just run:

heroku addons:add mongolab

Now open your Heroku app’s “/mongo” URL in your browser. Wahoo! You have a client/server browser app running on the cloud! Hopefully that has helped you to get a glimpse of where web application architecture is going. This is just part of the picture and I have a few other articles planned that will cover some of the other pieces. So keep watching here and let me know what you think.

Acknowledgments: Mike Slinn, a friend of mine that does Scala and Akka consulting, helped me understand BlueEyes and helped write some of the code for this project. Mike is also the author of the recently released book Composable Futures with Akka 2.0 with Java and Scala Code Examples.

Posted in BlueEyes, MongoDB, Scala | 4 Comments

Heroku at Jfokus and Spring I/O 2012

In just a few weeks I’ll be over in Europe presenting about Heroku at two fantastic Java conferences. First up is Jfokus in Stockholm! On February 14 at 20:00 I will be leading a Cloud Conversations BoF. Then on February 15 at 11:10 I will be speaking about how to “git push” Java & Play! Apps to the Cloud. This will be my first time speaking at Jfokus and I’m really excited because I’ve heard such great things.

On Thursday Feb 16 I will be at Spring I/O in Madrid speaking about Running Spring Apps on the Cloud with Heroku at 12:40.

Hope to see you there!

Posted in Conferences, Heroku, Java, Play Framework | Leave a comment

Try the New Play Framework Heroku Plugin

I just published a Heroku Plugin for Play Framework. Right now it just deploys a Play app to Heroku. Try it out:

Signup for a Heroku account

Install the Heroku plugin locally:
$ play install heroku

Create a Play (1.2.3 or 1.2.4) app:
$ play new foo --with heroku

Or if you already have an existing Play app, add the follow line to the conf/dependencies.yml file and then run “play deps –sync”:

    - play -> heroku 0.2
Deploy the app:
$ play heroku:deploy foo

You should see something like:

~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2.4, http://www.playframework.org
~
~ Deploying app to Heroku
Listening for transport dt_socket at address: 8000
Project directory: /home/jamesw/Desktop/foo
Read Heroku API key from /home/jamesw/.heroku/credentials
Created new ssh key pair (heroku_rsa) in: /home/jamesw/.ssh
Added the heroku_rsa.pub ssh public key to your Heroku account
Created a .git directory for your project
Added and committed all of the local changes to the git repo
Created app: cold-night-1511
http://cold-night-1511.herokuapp.com/
Added git remote: git@heroku.com:cold-night-1511.git
Deploying application via git push
Application deployed
~ App Deployed

Note: I haven’t figured out how to pipe the git push output to the screen yet, so be patient when the app is being git pushed. It’s working, just takes a minute.

Check out your Play app running on the cloud! Use the URL in the “heroku:deploy” output. This should work with new and existing Play apps.

All of the code for the Heroku Play module is on GitHub. There is more I want to do with this (scaling, logs, etc) and your contributions are certainly welcome! Keep checking back here for updates and let me know how it goes!

Posted in Heroku, Play Framework | 3 Comments

Java on Heroku at CinJUG, Detroit JUG, and MongoDB Boulder

Over the next few days I’ll be presenting about Java, Play Framework, and Scala on Heroku at a couple Java User Groups and a MongoDB conference:

Hope to see you there!

Posted in Conferences, Heroku, Java, Play Framework, Scala | Leave a comment


You are viewing a mobilized version of this site...
View original page here

Mobilized by Mowser Mowser