Platinum Partner
java,cloud,heroku,play framework,java playframework heroku

Step-by-Step for a Simple Twitter with Play Framework, AJAX, CRUD and Heroku

On August 31st, 2011: I will have the great honor to present our beloved Play Framework at Salesforce's Dreamforce conference here in San Francisco, CA. If you are attending, please feel free to check it out or just stop by to say hello. Thank you Zenexity for the opportunity! I am always excited to help spread the word on this awesome framework!

 

So the big announcement is out---Heroku started offering native support to Play Framework applications! If you haven't heard it, checkout the post from Jesper Joergensen on Heroku's blog.

 

So for the presentation, I am setting up a very basic Twitter clone; it's meant to be simple yet it displays just enough of the productivity that Play! provides. I am gonna go through the steps to setup the demo application which should cover what was announced on Heroku's blog post but with a little more depth.

 

 

  • First step let's create the application

  • play new twitter

     

     

  • Add dependency to CRUD module (conf/dependencies.yml)

  • - play -> crud

     

     

  • Get the dependencies

  • play dependencies

     

     

  • IDE Integration

  • play eclipsify (for Eclipse), play idealize (for IntelliJ) or play netbeansify (for Netbeans).

     

     

  • Create Model (app/models/Tweet.java)

  • package models;
    
    import java.util.Date;
    import java.util.List;
    
    import javax.persistence.Entity;
    
    import play.data.validation.MaxSize;
    import play.data.validation.Required;
    import play.db.jpa.Model;
    
    @Entity
    public class Tweet extends Model {
    
    @Required
    @MaxSize(140)
    public String tweet;
    
    @Required
    public Date createDate = new Date();
    
    public static List findLatest() {
    return Tweet.find("order by createDate desc").fetch();
    }
    
    @Override
    public String toString() {
    return this.tweet;
    }
    
    }
    

     

     

  • Define DB for JPA Models (conf/application.conf)

  • db=${DATABASE_URL}

     

     

  • Add Controller Actions (app/controllers/Application.java)

  • package controllers;
    
    import java.util.List;
    
    import models.Tweet;
    import play.mvc.Controller;
    
    public class Application extends Controller {
    
    public static void index() {
    List tweets = Tweet.findLatest();
    render(tweets);
    }
    
    public static void create(String msg) {
    Tweet tweet = new Tweet();
    tweet.tweet = msg;
    tweet.save();
    render(tweet);
    }
    
    public static void tweets() {
    List tweets = Tweet.findLatest();
    renderJSON(tweets);
    }
    }
    

     

     

  • Define Main View (app/views/Application/index.html)

  • #{extends 'main.html' /}
    #{set title:'Home' /}
    
    <!-- Create Tweet Form -->
    
    <form> <input name="tweet" type="text" />
    <input type="submit" value="Tweet" /> </form><!-- Latest Tweets List -->
    <ul> #{list tweets}
    <li>${_.tweet} (${_.createDate.since()})</li><p><p>
    #{/list}</ul>
    <!-- JS -->
    <script type="text/javascript">
    
    // Capture Form Submit Event
    $('form').submit(function() {
    // Define Create Action
    var createAction = #{jsAction @create(':tweet') /}
    
    // Call Create Action
    $.post(createAction({tweet: $('input:first').val()}), function(data) {
    // Prepend Results to the List
    $('ul').prepend(data);
    $('input:first').val('');
    
    });
    
    // Don't let the browser redirect
    return false;
    });
    
    </script>
    

     

     

  • Define Create Action View (app/views/Application/create.html)

  • <!-- Single Item Render (after save action) -->
    
    <li><code>${tweet.tweet} (${tweet.createDate.since()})</li>
    

     

     

  • Create Unit Test for Tweet Model

  • import models.Tweet;
    
    import org.junit.Assert;
    import org.junit.Test;
    
    import play.test.UnitTest;
    
    public class TweetTest extends UnitTest {
    
    @Test
    public void testModelSave() {
    long count = Tweet.count();
    Tweet t = new Tweet();
    t.tweet = "my sample tweet";
    t.save();
    long count2 = Tweet.count();
    Assert.assertEquals(count + 1, count2);
    }
    
    }
    
     
  • Create CRUD Admin for Tweet Model

  • package controllers;
    public class Tweets extends CRUD {
    }
    
     
  • Add Routes (conf/routes)

  • * /admin module:crud

     

     

  • Define Messages for CRUD Admin (conf/messages)

  • tweet=Tweet
    createDate=Date Created

     

     

  • Define Procfile

  • web: play run --%$FRAMEWORK_ID --http.port=$PORT -DusePrecompiled=$USE_PRECOMPILED -DDATABASE_URL=mem

     

     

  • Run in Development

  • play run --%dev -DusePrecompiled=false -DDATABASE_URL=mem

     

     

  • Create Application on Heroku

  • heroku create play-twitter --stack cedar

     

     

  • Setup Git Repository

  • git init; git add .; git commit -a -m "Initial Commit"; git remote add heroku git@heroku.com:play-twitter.git

     

     

  • Setup Heroku Environment Variables

  • heroku config:add FRAMEWORK_ID=prod; heroku config:add USE_PRECOMPILED=true

     

     

  • Deploy to Heroku

  • git push heroku master

     

     

  • If anything went wrong you can always check the log

  • heroku logs

     

     

  • To Setup a Real Database on Heroku

  • heroku addons:add shared-database

     

    You can checkout a live demo here, the admin interface here or clone the source code on Github.

     

    Voila! Now Go Play!

     

    Originally posted at geeks.aretotally.in/twitter-playframework-heroku.

    {{ tag }}, {{tag}},

    {{ parent.title || parent.header.title}}

    {{ parent.tldr }}

    {{ parent.urlSource.name }}
    {{ parent.authors[0].realName || parent.author}}

    {{ parent.authors[0].tagline || parent.tagline }}

    {{ parent.views }} ViewsClicks
    Tweet

    {{parent.nComments}}