Play framework is joining the Typesafe Stack — More information in the official announcement

Meet the community

Planet Play

Here are collected blog posts from the Play! community. The content is uncensored, unfiltered and represents the views of the individual community members. To have your blog included, post your application to the Google Group.

Playframework, Twitter Bootstrap and Google Maps API Published January 2, 2012 on Wayne

So, what did you do over the Christmas break? Presents, plenty of family time, kick back a little? I did all that and wrote a little web application as well. I thought I would share a little insight into how I got on.

Background

A while back, I created a publicly shared google map so that anyone interested in Play framework could add themselves to the map. A decent number of people signed up, but it was a pain to maintain. There was no control over who could put what where. For example, someone could delete someone else’s pinpoint, change someone else’s details, or the most common issue, overwrite the play framework description and URL’s. So, I decided to create a web application that would allow the community to have a developer map, but without the issues of a simple shared google map.

The tools

Obviously, I used the Playframework, but additionally I decided to Bootstrap from Twitter. Bootstrap, if you haven’t used it yet, is a CSS base that offers a way to develop clean designs and neat interfaces. There are plenty of blogs already about how to use bootstrap, and the documentation itself is pretty complete, but suffice to say, it made the job of building the UI significantly easier. As I am not a naturally artistic person, Bootstrap has allowed me to build a UI I am proud of, without having to suffer for the cause. It fits in with the “just-works” approach of Play, it makes what should be simple, simple.

Secondly, I used Google Maps to render the maps and the icons on top of the maps. I have used Google Maps before, but decided to check out Bing Maps before making my final choice. Put simply, I found Google Maps to do everything I needed, with relative ease, and found no reason why Bing maps could be a better choice.

Quite simply, Play, Bootstrap and GoogleMaps work amazingly well together.

Deployment

As most people tend to do, I decided to deploy the code onto Heroku. I have used Heroku a few times previously, and have had good experiences with it. I was tempted to try something else, due to the limit on the database size of the free account, but as I already have hosting elsewhere, I decided to just use the database on my paid-for hosting alongside Heroku as the application server. Even with this separation, the response times for the application are excellent. It has made me wonder whether there is a gap in the market for a low-end Database-as-a-Service facility to bridge the gap between the Heroku Postgres offerings.

I did have one issue with the deployment, which you may want to be aware of. My views were all lowercase HTML files, rather than camelCase, which was the case for my controller actions. On my Macbook Pro this made no difference, but as soon as I deployed to Heroku I started getting errors. It took me a while to figure this out, because the error logging wasn’t working ver well. Unfortunately I had already committed my code to the local git repository on my mac, which did not care about case differences, so I had to fight with a few git mv commands to move the files to uppercase equivalents. Other than that, the whole thing has worked out pretty well.

Next Steps

Well, its still in beta, so if you guys like it, and it starts to take off, expect more features to start appearing. What I am hoping for is for the word to spread, so that more and more people add themselves to the maps (why not start with the play framework map). Additionally, I would hope that people will create maps for other technologies that they are interested in.

If you have any thoughts or comments, please feel free to get in touch!


Read the original post…

Where’s Felipe? A Location-based Play Framework, Scala, Google Maps Clustering, PostgreSQL, Heroku and Anorm App Published December 31, 2011 on Felipe Oliveira

Post image for Where’s Felipe? A Location-based Play Framework, Scala, Google Maps Clustering, PostgreSQL, Heroku and Anorm App

As I mentioned in a past article, Why Did I Fall in Love with Play! Framework?, I was the tech lead for a few real estate deployments for Fannie Mae, HUD, Foreclosure.com, etc; as you know, real estate is all about LOCATION! LOCATION! LOCATION!

I’m on vacation, but I am still a geek (and my wife is still sleeping!) so I decided to create a location-based application using the all-awesomeness of Play Framework, Scala, Google Maps v3, PostgreSQL and Anorm; you know, for ol’ times’ sake! On the map-side I will show you how to solve the very common “too many markers” problem (see image below) using clustering to group the markers.

See a live demo running on Heroku right here! The complete source code is available at https://github.com/feliperazeek/where-is-felipe. Thank you my crazy French friend Pascal (author of Siena) for the review.

  • First let’s create the data transfer classes returned by the Controller in JSON form and used by Google Maps (markers and clusters). These are very simple classes which will just hold data used by the thin RESTful layer.
  • /**
     * Map Marker
     *
     * @author Felipe Oliveira [@_felipera]
     */
    case class MapMarker(id: String, latitude: Double, longitude: Double, address: Option[String], city: Option[String], state: Option[String], zip: Option[String], county: Option[String])
    
    /**
     * Map Cluster
     *
     * @author Felipe Oliveira [@_felipera]
     */
    case class MapCluster(geohash: String, count: Long, latitude: Double, longitude: Double)
    
    /**
     * Map Cluster Companion
     *
     * @author Felipe Oliveira [@_felipera]
     */
    object MapCluster {
    
        /**
         * Constructor
         */
        def apply(geohash: String, count: Long): MapCluster = {
            val coords = GeoHashUtils decode geohash
            new MapCluster(geohash, count, coords(0), coords(1))
        }
    
    }
    
    /**
     * Map Overlay
     *
     * @author Felipe Oliveira [@_felipera]
     */
    case class MapOverlay(markers: List[MapMarker], clusters: List[MapCluster])
  • Second let’s define the model classes using Play Framework’s Anorm. There’s only one model defined—it’s called Site. That’s a very simple model which contains only basic fields, such as id, address, city, state, city, zip, county, latitude, longitude and geohash. Geohash uniquely identifies geographical areas, a system created by Gustavo Niemyer, and it has many limitations in comparison to true GIS tools, such as PostgreSQL’s PostGIS or search indexes with geo-features (like my personal favorite ElasticSearch). Although geohash has its share of limitations, it’s a very easy way to add geographical capabilities using data stores without GeoSpatial capabilities such as MySQL. In this case, I am using geohashes to group markers, the so-called marker clusters (punches in bunches, baby!). Click here to find a good representation on how geohashes work. I am using the geohash encoder and decoder from Lucene Spatial, very easy to use.
    /**
     * To String Trait
     *
     * @author Felipe Oliveira [@_felipera]
     */
    trait ToString {
        self: Entity =>
    
        /**
         * Reflection-Based ToString
         */
        override def toString = ToStringBuilder.reflectionToString(this)
    
    }
    
    /**
     * Entity Base Class
     *
     * @author Felipe Oliveira [@_felipera]
     */
    trait Entity extends ToString
    
    /**
     * Site Model
     *
     * @author Felipe Oliveira [@_felipera]
     */
    case class Site(
            var id: Pk[Long],
            @Required var name: Option[String],
            @Required var address: Option[String],
            @Required var city: Option[String],
            @Required var state: Option[String],
            @Required var zipcode: Option[String],
            @Required var county: Option[String],
            @Required var latitude: Option[Double],
            @Required var longitude: Option[Double]) extends Entity {
    
        /**
         * Constructor
         */
        def this(address: Option[String], city: Option[String], state: Option[String], zipcode: Option[String], county: Option[String], latitude: Option[Double], longitude: Option[Double]) {
            this(NotAssigned, None, address, city, state, zipcode, county, latitude, longitude)
        }
    
    }
    
    /**
     * Site Companion Object
     *
     * @author Felipe Oliveira [@_felipera]
     */
    object Site extends Magic[Site] {
    
        /**
         * Count
         */
        def count(implicit filters: SearchFilters): Long = statement("select count(1) as count from Site").as(scalar[Long])
    
        /**
         * Map Overlay
         */
        def mapOverlay(implicit filters: SearchFilters): MapOverlay = {
            // Get Map Clusters
            val clusters = mapClusters
    
            // Get Markers
            filters.geohashes = Option(clusters.filter(_.count == 1).map(_.geohash).toList)
            val markers = mapMarkers
    
            // Define Map Overlay
            new MapOverlay(markers, clusters.filter(_.count > 1))
        }
    
        /**
         * Map Clusters
         */
        def mapClusters(implicit filters: SearchFilters): List[MapCluster] = {
            // Get Query
            val query = statement("select " + geohashExpression + " as geohash, count(1) as count from Site", "group by " + geohashExpression + " order by count desc")
    
            // Get Results
            val list: List[MapCluster] = query().filter(_.data(0) != null).map {
                row =>
                    {
                        // Get Fields
                        val fields = row.data
    
                        // Geohash
                        Option(fields(0)) match {
                            case Some(geohash: String) => {
                                // Count
                                val count: Long = fields(1).toString.toLong
    
                                // Map Cluster
                                MapCluster(geohash, count)
                            }
                            case _ => null
                        }
                    }
            } toList
    
            // Log Debug
            please log "Map Clusters: " + list.size
    
            // Return List
            list.filter(_ != null)
        }
    
        /**
         * Map Markers
         */
        def mapMarkers(implicit filters: SearchFilters): List[MapMarker] = {
            // Get Query
            val query = statement("select site.* from Site site", "order by id")
    
            // Get Results
            val list: List[MapMarker] = query().map {
                row =>
                    try {
                        // Id
                        val id = row[String]("id")
    
                        // Fields
                        val address = row[Option[String]]("address")
                        val city = row[Option[String]]("city")
                        val state = row[Option[String]]("state")
                        val zip = row[Option[String]]("zip")
                        val county = row[Option[String]]("county")
                        val latitude = row[Option[Double]]("latitude")
                        val longitude = row[Option[Double]]("longitude")
    
                        // Map Marker (coord required)
                        (latitude, longitude) match {
                            case (lat: Some[Double], lng: Some[Double]) => new MapMarker(id, lat.get, lng.get, address, city, state, zip, county)
                            case _ => null
                        }
    
                    } catch {
                        case error: Throwable => {
                            please report error
                            null
                        }
                    }
            } toList
    
            // Log Debug
            please log "Map Markers: " + list.size
    
            // Return List
            list
        }
    
        /**
         * Statement
         */
        def statement(prefix: String, suffix: Option[String] = None)(implicit filterBy: SearchFilters) = {
            // Params
            val geohashes = filterBy geohashes
            val zoom = filterBy zoom
            val geohashPrecision = filterBy geohashPrecision
    
            // Params will contain the list of name/value pairs that need to be bound to the query
            val params = new HashMap[String, Any]
    
            // This is gonna define the statement that we'll use on the find method
            val terms = new StringBuffer
            terms.append(prefix)
            terms.append(" where ")
    
            // Boundary
            filterBy.hasBounds match {
                case true => {
                    params += "nw" -> filterBy.nw.get
                    params += "ne" -> filterBy.ne.get
                    params += "se" -> filterBy.se.get
                    params += "sw" -> filterBy.sw.get
                    terms.append("latitude between {nw} and {ne} and longitude between {sw} and {se} and ")
                }
                case _ => please log "Ignoring Map Bounds!"
            }
    
            // Geohashes
            geohashes match {
                case Some(list) => {
                    if (!list.isEmpty) {
                        val values = list.map(_.substring(0, geohashPrecision)).toSet
                        terms.append(geohashExpression + " in (" + multiValues(values) + ") and ")
                        terms.append("geohash is not null and ")
                    }
                }
                case _ => please log "Not including geohashes in query!"
            }
    
            // Final one just in case
            terms.append("1 = {someNumber} ")
    
            // Suffix
            terms.append(suffix.getOrElse(""))
    
            // Define SQL
            val sql = terms.toString.trim
    
            // Define Query
            var query = SQL(sql).on("someNumber" -> 1)
            for (param <- params) {             please log "Bind - " + param._1 + ": " + param._2             query = query.on(param._1 -> param._2)
            }
    
            // Return Query
            query
        }
    
        /**
         * Geohash Expression
         */
        def geohashExpression(implicit filterBy: SearchFilters): String = filterBy.zoom match {
            case Some(z: Int) if z > 0 => "substring(geohash from 1 for " + filterBy.geohashPrecision.toString + ")"
            case _ => "geohash"
        }
    }
  • Then let’s define the search filters.
    /**
     * Search Filters
     *
     * @author Felipe Oliveira [@_felipera]
     */
    case class SearchFilters(var ne: Option[Double], var sw: Option[Double], var nw: Option[Double], var se: Option[Double], var geohashes: Option[List[String]] = None, var zoom: Option[Int] = None) {
    
        /**
         * Log Debug
         */
        please log "NE: " + ne
        please log "SW: " + sw
        please log "NW: " + nw
        please log "SE: " + se
        please log "Geohashes: " + geohashes
        please log "Zoom: " + zoom
    
        /**
         * Format Date
         */
        def format(date: Date) = dateFormat format date
    
        /**
         * Geohash Precision
         */
        def geohashPrecision: Int = zoom match {
            case Some(z: Int) if z > 0 => 22 - z
            case _ => 1
        }
    
        /**
         * Geohash Suffix
         */
        def geohashSuffix: String = geohashPrecision toString
    
        /**
         * Has Bounds
         */
        def hasBounds: Boolean = {
            please log "Has Bounds? NE: " + ne + ", SW: " + sw + ", NW: " + nw + ", SE: " + se
            if (ne.valid && nw.valid && nw.valid && se.valid) {
                please log "Yes!"
                true
            } else {
                please log "No!"
                false
            }
        }
    
        /**
         * To Query String
         */
        def toQueryString = {
            // Start
            val queryString = new StringBuilder
    
            // Map Bounds
            if (hasBounds) {
                queryString append "ne=" append ne append "&"
                queryString append "sw=" append sw append "&"
                queryString append "nw=" append nw append "&"
                queryString append "se=" append se append "&"
            }
    
            // Zoom
            zoom match {
                case Some(s) => queryString append "zoom=" append s append "&"
                case _ => please log "No zoom level defined!"
            }
    
            // Log Debug
            please log "Query String: " + queryString
            queryString.toString
        }
    
    }
  • And a bunch of sugar!
    package pretty
    
    import play.Logger
    import play.mvc.Controller
    import org.apache.commons.lang.exception.ExceptionUtils
    import net.liftweb.json.Printer._
    import net.liftweb.json.JsonAST._
    import net.liftweb.json.Extraction._
    import java.util.{ Calendar, Date }
    import org.joda.time.Months
    import java.net.URLEncoder
    import java.text.SimpleDateFormat
    import org.apache.commons.lang.StringUtils
    import play.Logger
    import org.joda.time.DateTime
    import java.util.Date
    import java.sql.Timestamp
    
    /**
     * Helper Object
     *
     * @author Felipe Oliveira [@_felipera]
     */
    object please {
    
        /**
         * JSON Formats
         */
        implicit val formats = PlayParameterReader.Formats.formats
    
        /**
         * Compress
         */
        def compress[A](ls: List[A]): List[A] = {
            ls.foldRight(List[A]()) {
                (h, r) =>
                    if (r.isEmpty || r.head != h) {
                        h :: r
                    } else {
                        r
                    }
            }
        }
    
        /**
         * Time Execution
         */
        def time[T](identifier: String = "n/a")(runnable: => T): T = {
            throwOnError {
                // Define Search Start Time
                val started = new Date
    
                // Execute Action
                val results: T = runnable
    
                // Define Duration Time
                logOnError[Unit] {
                    val ended = new Date
                    val duration = ended.getTime - started.getTime
                    Logger.info("Runnable: " + identifier + ", Duration: " + duration + "ms (" + (duration / 1000.0) + "s)")
                }
    
                // Return Results
                results
            }
        }
    
        /**
         * Now
         */
        def now = new Date()
    
        /**
         * Current Time
         */
        def currentTime = now.getTime
    
        /**
         * Log
         */
        def log(any: String) = Logger info any
    
        /**
         * Report Exception
         */
        def report(error: Throwable) = Logger error ExceptionUtils.getStackTrace(error)
    
        /**
         * Dummy Controller
         */
        private val _dummy = new Controller {}
    
        /**
         * Conf
         */
        def conf(name: String) = play.Play.configuration.getProperty(name)
    
        /**
         * Multi Values
         */
        def multiValues(values: Iterable[String]) = values.mkString("'", "','", "'")
    
        /**
         * Log If Error
         */
        def logOnError[T](runnable: => T): Option[T] = {
            try {
                Some(runnable)
            } catch {
                case error: Throwable =>
                    please report error
                    None
            }
        }
    
        /**
         * Throw if Error
         */
        def throwOnError[T](runnable: => T): T = {
            try {
                runnable
            } catch {
                case error: Throwable => {
                    please report error
                    throw new RuntimeException(error fillInStackTrace)
                }
            }
        }
    
        /**
         * URL Encode
         */
        def encode(value: String) = URLEncoder.encode(value, conf("encoding"))
    
        /**
         * Automatically generate a standard perks json response.
         */
        def jsonify(runnable: => Any) = {
            _dummy.Json(pretty(render(decompose(
                try {
                    val data = runnable match {
                        // Lift-json has a cow if you pass it a mutable map to render.
                        case mmapResult: Map[Any, Any] => mmapResult.toMap
                        case result => result
                    }
                    Map("status" -> 200, "data" -> data)
                } catch {
                    case error: Throwable =>
                        please report error
                        Map("status" -> 409, "errors" -> Map(error.hashCode.toString -> error.getMessage))
                }
            ))))
        }
    
        /**
         * Option[Date] to Pimp Date Implicit Conversion
         */
        implicit def date2PimpDate(date: Option[Date]) = new PimpDate(date.getOrElse(new Date))
    
        /**
         * Option[Date] to Date Implicit Conversion
         */
        implicit def optionDate2Date(date: Option[Date]) = date.getOrElse(new Date)
    
        /**
         * Int to Pimp Int
         */
        implicit def int2PimpInt(i: Int) = new PimpInt(i)
    
        /**
         * String to Date
         */
        implicit def stringToDate(string: String): Date = dateFormat parse string
    
        /**
         * Date to String
         */
        implicit def dateToString(date: Date): String = dateFormat format date
    
        /**
         * Option Date to String
         */
        implicit def optionDate2String(date: Option[Date]): String = date match {
            case Some(d: Date) => d
            case _ => "n/a"
        }
    
        /**
         * Option Double to Pimp Option Double
         */
        implicit def optionDoubleToPimpOptionDouble(value: Option[Double]): PimpOptionDouble = new PimpOptionDouble(value)
    
        /**
         * String to Double
         */
        implicit def stringToDouble(str: Option[String]): Double = {
            str match {
                case Some(s) => {
                    try {
                        s.toDouble
                    } catch {
                        case ne: NumberFormatException => 0.0
                        case error: Throwable => 0.0
                    }
                }
                case _ => 0.0
            }
        }
    
        /**
         * Date Format
         */
        def dateFormat = new SimpleDateFormat("MM/dd/yyyy")
    
        /**
         * String to Option String
         */
        implicit def string2OptionString(value: String): Option[String] = Option(value)
    
        /**
         * Option String to String
         */
        implicit def optionString2String(value: Option[String]): String = value.getOrElse("n/a")
    
        /**
         * String to Option Double
         */
        implicit def string2OptionDouble(value: String): Option[Double] = try {
            if (StringUtils.isNotBlank(value)) {
                Option(value.toDouble)
            } else {
                None
            }
        } catch {
            case error: Throwable => {
                please report error
                None
            }
        }
    
        /**
         * Dinossaur Birth Date
         */
        def dinoBirthDate = {
            val c = Calendar.getInstance()
            c.set(0, 0, 0)
            c.getTime
        }
    
    }
    
    /**
     * Pimp Int
     *
     * @author Felipe Oliveira [@_felipera]
     */
    case class PimpInt(value: Int) {
    
        /**
         * Months Ago
         */
        def monthsAgo = {
            val c = Calendar.getInstance()
            c.setTime(new Date)
            c.add(Calendar.MONTH, (value * -1))
            c.getTime
        }
    
    }
    
    /**
     * Pimp Option Double
     *
     * @author Felipe Oliveira [@_felipera
     */
    case class PimpOptionDouble(value: Option[Double]) {
    
        /**
         * Is Valid
         */
        def valid: Boolean = value.getOrElse(0.0) != 0.0
    
    }
    
    /**
     * Pimp Date
     *
     * @author Felipe Oliveira [@_felipera]
     */
    class PimpDate(date: Date) {
    
        /**
         * Is?
         */
        def is = {
            Option(date) match {
                case Some(d) => d
                case _ => new Date
            }
        }
    
        /**
         * Before?
         */
        def before(other: Date) = date.before(other)
    
        /**
         * After?
         */
        def after(other: Date) = date.after(other)
    
        /**
         * Past?
         */
        def past = date.before(new Date)
    
        /**
         * Future?
         */
        def future = date.after(new Date)
    
        /**
         * Subtract
         */
        def -(months: Int) = {
            val c = Calendar.getInstance()
            c.setTime(date)
            c.add(Calendar.MONTH, (months * -1))
            c.getTime
        }
    
    }
    
    /**
     * Clockman Object
     *
     * @author Felipe Oliveira [@_felipera]
     */
    object Clockman {
    
        /**
         * Pimp Date
         */
        def is(date: Date) = new PimpDate(date)
    
    }
  • Then let’s define the controllers.
    /**
     * Filters Trait
     *
     * @author Felipe Oliveira [@_felipera]
     */
    trait Filters {
        self: Controller =>
    
        /**
         * Search Filters
         */
        def filters = new SearchFilters(ne, sw, nw, se, zoom = zoom)
    
        /**
         * Zoom
         */
        def zoom: Option[Int] = Option(params.get("zoom")) match {
            case Some(o: String) => Option(o.toInt)
            case _ => Option(1)
        }
    
        /**
         * NE Bound
         */
        def ne = boundParam("ne")
    
        /**
         * SW Bound
         */
        def sw = boundParam("sw")
    
        /**
         * NW Bound
         */
        def nw = boundParam("nw")
    
        /**
         * SE Bound
         */
        def se = boundParam("se")
    
        /**
         * Bound Param
         */
        def boundParam(name: String): String = Option(params.get(name)).getOrElse("")
    
    }
    
    /**
     * Main Controller
     *
     * @author Felipe Oliveira [@_felipera]
     */
    object Application extends Controller with controllers.Filters {
    
        /**
         * Index Action
         */
        def index = time("index") {
            views.Application.html.index(filters)
        }
    
    }
    
    /**
     * Geo Controller
     *
     * @author Felipe Oliveira [@_felipera]
     */
    object Geo extends Controller with controllers.Filters {
    
        /**
         * Map Overlay
         */
        def mapOverlay = time("mapOverlay") {
            jsonify {
                implicit val searchWith = filters
                Site mapOverlay
            }
        }
    
    }
  • Now it’s time for the frontend code, it’s mostly sugar so I am just gonna show you the JavaScript part of it, the important piece. Basically it defined the map, calls the RESTful MapOverlay API, grabs the markers and clusters and bind them to the map!
    // "Da" Map
    var map;
    
    // Global Markers Array
    var markers = [];
    
    // Global Debug Flag
    var debug = true;
    if (console == null) {
        debug = false;
    }
    
    // Log Function
    function log(msg) {
        if (debug) {
            console.log(msg);
        }
    }
    
    // Initialize Map
    function initialize() {
        // Map Options
        var myOptions = {
              zoom: 8,
              mapTypeId: google.maps.MapTypeId.ROADMAP
        };
    
        // Define Map
        map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);
    
        // Set Map Position
        map.setCenter(new google.maps.LatLng(40.710623, -74.006605));
    
        // Load Markers
        loadMarkers(map, null);
    
        // Listen for Map Movements
        google.maps.event.addListener(map, 'idle', function(ev) {
                log("Idle Listener!");
                var bounds = map.getBounds();
                var ne = bounds.getNorthEast(); // LatLng of the north-east corner
                var sw = bounds.getSouthWest(); // LatLng of the south-west corner
                var nw = new google.maps.LatLng(ne.lat(), sw.lng());
                var se = new google.maps.LatLng(sw.lat(), ne.lng());
                var q = "&ne=" + ne.lat() + "&sw=" + sw.lng() + "&nw=" + sw.lat() + "&se=" + ne.lng();
                log("Map Bounds: " + q);
                clearOverlays();
                loadMarkers(map, q);
            });
    }
    
    // Clear Markers
    function clearOverlays() {
        log("Clear Overlays!");
        if (markers != null) {
            for (i in markers) {
                markers[i].setMap(null);
            }
        }
        markers = new Array();
    }
    
    // Cap Words
    function capWords(str){
        if (str == null) {
            return "";
        }
        str = str.toLowerCase();
       words = str.split(" ");
       for (i=0 ; i < words.length ; i++){
          testwd = words[i];
          firLet = testwd.substr(0,1); //lop off first letter
          rest = testwd.substr(1, testwd.length -1)
          words[i] = firLet.toUpperCase() + rest
       }
       return words.join(" ");
    }
    
    // Load Markers
    function loadMarkers(map, extra) {
        $(document).ready(function() {
            zoomLevel = map.getZoom();
            if (zoomLevel == null) {
                zoomLevel = 1;
            }
            var url = '/mapOverlay';
            if (document.location.search) {
                url = url + document.location.search;
            } else {
                url = url + "?1=1"
            }
            if (extra != null) {
                url = url + extra;
            }
            url = url + "&zoom=" + zoomLevel;
            log('URL: ' + url);
            $.getJSON(url, function(json) {
                markers = new Array(json.data.markers.length);
                for (i = 0; i < json.data.markers.length; i++) {
                      // Get Marker
                      var marker = json.data.markers[i];
    
                      // Customer Logo
                      var icon = "http://geeks.aretotally.in/wp-content/uploads/2011/03/html5_geek_matt_16.png";
                      var logo = "http://geeks.aretotally.in/wp-content/uploads/2011/03/html5_geek_matt_32.png";
                      var width = 32;
                      var height = 32;
                      var customer = marker.customer;
    
                      // console.log('Marker: ' + marker + ', Lat: ' + marker.latitude + ', Lng: ' + marker.longitude);
                      var contentString = marker.address + ' ' + marker.city + ', ' + marker.state + ' ' + marker.zip;
    
                      var position = new google.maps.LatLng(marker.latitude, marker.longitude);
    
                      var m = new google.maps.Marker({
                          position: position,
                          icon: icon,
                          html: contentString
                      });
    
                      markers[i] = m;
                }
    
                // Clusters
                for (i = 0; i < json.data.clusters.length; i++) {
                    var cluster = json.data.clusters[i];
                    log('Cluster: ' + cluster);
    
                    var position = new google.maps.LatLng(cluster.latitude, cluster.longitude);
    
                    for (c = 0; c < cluster.count; c++) {
                      log('Cluster Item: ' + c);
                      var m = new google.maps.Marker({
                          position: position
                      });
    
                      markers[i] = m;
                    }
                }
    
                // Marker Cluster
                var clusterOptions = { zoomOnClick: true }
                var markerCluster = new MarkerClusterer(map, markers, clusterOptions);
    
                // Info Window
                var infowindow = new google.maps.InfoWindow({
                    content: 'Loading...'
                });
    
                // Info Window Listener for Markers
                for (var i = 0; i < markers.length; i++) {
                    var marker = markers[i];
                    google.maps.event.addListener(marker, 'click', function () {
                        // Log Debug
                        log('Marker Click!');
    
                        // Set Info Window Marker Content
                        infowindow.close();
                        infowindow.setContent(this.html);
    
                        // Set Current Marker
                        var currentMarker = this;
    
                        // Get Map Position
                        var mapLatLng = map.getCenter();
                        var markerLatLng = currentMarker.getPosition();
    
                        // Check Coordinate
                        if (!markerLatLng.equals(mapLatLng)) {
                            // Map will need to pan
                            map.panTo(markerLatLng);
                            google.maps.event.addListenerOnce(map, 'idle', function() {
                                // Open Info Window
                                infowindow.open(map, currentMarker);
                                setTimeout(function () { infowindow.close(); }, 5000);
                            });
                        } else {
                            // Map won't be panning, which wouldn't trigger 'idle' listener so just open info window
                            infowindow.open(map, currentMarker);
                            setTimeout(function () { infowindow.close(); }, 5000);
                        }
                    });
                }
    
            });
        });
    }
    
    // Initialize Map
    google.maps.event.addDomListener(window, 'load', initialize);
  • Happy New Year! 2011 was a great year, I can’t wait for 2012!

    Read the original post…

    Klout Search Powered by ElasticSearch, Play Framework, Scala and Akka Published December 9, 2011 on Felipe Oliveira

    Post image for Klout Search Powered by ElasticSearch, Play Framework, Scala and Akka

    At Klout, we love data and as Dave Mariani, Klout’s VP of Engineering, stated in his latest blog post, we’ve got lots of it! Klout currently uses Hadoop to crunch large volumes of data but what do we do with that data? You already know about the Klout score, but I want to talk about a new feature I’m extremely excited about — search!

     

    Problem at Hand


    I just want to start off by saying, search is hard! Yet, the requirements were pretty simple:  we needed to create a robust solution that would allow us to search across all scored Klout users. Did I mention it had to be fast? Everyone likes to go fast! The problem is that 100 Million People have Klout (and that was this past September—an eternity in Social Media time) which means our search solution had to scale, scale horizontally.

    So how did we accomplish that?

     

    Share Nothing and Don’t Block


    We use Node.js in our front end to help scale to thousands of concurrent users.  We follow the same philosophy in our backend for search. Given the size of our dataset and its substantial growth rate, we needed to choose a search solution which would allow us to scale horizontally; On the application side we wanted to have a stateless Web layer, not only for performance, but also for manageability. So share nothing and block as little as possible!

     

    Let’s Play! and be “cool, bonsai cool”


    The technology stack chosen to address the problem was ElasticSearch and the Play! Framework. Why did we choose that stack? At Klout, we like to choose the right tool for the job, regardless of the platform it runs under or the company that’s behind it.  We chose ElasticSearch and Play! because both of these were designed to use fast, non-blocking IO, both of these provide powerful infrastructure, and both of these were designed to be easy to extend.  These tools help us build powerful search now, and continue improving search to give you more relevant results.

    ElasticSearch is a powerful, scalable and distributed search solution built on strong foundations like JBoss Netty and Apache Lucene. ElasticSearch builds off of Apache Lucene, a personal favorite of mine, created by Doug Cutting.  Doug Cutting has had a huge impact on many tools we use at Klout;  He is also the creator of Hadoop (and Nutch for that matter!).  Lucene is a search library—more than 10 years old—that provides powerful search capabilities such as relevancy ranking, fuzzy matching, wildcard, proximity operators, fielded searching, spell-checking, multi-lingual and all that jazz—all while still being completely portable since it’s a JVM-based solution; most important, it’s blazing fast!

    ElasticSearch uses JBoss Netty as its network library for async/non-blocking IO.  In a traditional blocking IO model, performing a search across multiple shards would be extremely expensive.  We could retrieve results serially, meaning that our search would become slower as our data size increased, or execute results in parallel threads, which would require ever increasing processing resources.  Netty allows ElasticSearch to retrieve results from multiple search nodes in parallel; there are no blocking threads waiting for it to finish.

    We used Play! Framework for the Web layer, which also uses JBoss Netty as its network library. Why? To find out more about this great framework, watch my Dreamforce presentation from this past September here in San Francisco, CA: “Introducing Play! Framework: Painless Java and Scala Web Applications”. Just recently, Play! has joined Typesafe, the creators of Scala, as an official part of its Scala-based technology stack and providers of the Web solution for Scala.

    Akka is also part of Typesafe’s stack and provides an event-driven and self-healing concurrency platform based on an Erlang-style, actor-based concurrency model for the JVM. In summary, Akka helps Klout’s search go fast! We have actors for the different searches we support, messages are dispatched to their mailboxes as Play’s controller actions are invoked. Akka actors, which are pretty similar to Scala actors, allow us to effortlessly execute parallel searches to minimize overall response time to provide our users the best experience possible.

    If you are down to Play! come join us and follow us on Twitter as @_felipera and @dwollen.

    Happy Searching!

     

    Read the original post…

    Why Play isn’t a Java web framework Published November 29, 2011 on Lunatech Research

    Play isn’t really a Java web framework. Java’s involved, but that isn’t the whole story.

    ‘Java’ refers to two different things these days, and only one of them’s a programming language. Increasingly, when people talk about ‘Java’ they are really talking about one or more aspects of the wider platform, which includes the programming language, but also the Java Virtual Machine, the Java SE SDK or the many APIs that make up the broader landscape of Java EE and in-progress JSRs. After all, we keep seeing conference presentations where the programming language isn’t Java.

    More subtly, Java EE is not so much a landscape as a whole country, with its own culture - norms and values, if you like.

    Eating pasta

    Java EE is the land of the architectural pattern. I’m not sure which country that is, but it would have to be one where people eat a lot of pasta, with its many related code-style metaphors. What’s more, the architecture astronauts who live there have made the endless layers of lasagne architecture their national dish.

    Play, on the other hand, is from somewhere else. Play 1.0 was written in Java and using Play 1.2 is currently the best way to build a web application in Java, but this has little to do with the established Java EE culture or the monsters it spawns. And even though the ugly beasts known as EJB 2.1 and JSF 1.2 eventually spawned more docile offspring (EJB 3 and JSF 2), they are merely tamed and not companions that you would want to Play with.

    Emigrating to the web

    The country that Play comes from is called the World-Wide Web (country code ‘www’), where people live happy joyful lives, get things done with minimal fuss, and tell jingoistic jokes about their Java EE neighbours. Fortunately for Java developers who are tired of being at the wrong end of these jokes, the immigration policy is welcoming and the language is easy to learn - an HTTP server can be as small as 1074 bytes or 3 mm long.

    The first version of the Play framework may have been written in Java, but it had little to do with Java common practice or the established Java web APIs, and avoided the standard Servlet API entirely. Play used the Java language, but little else from the Java ecosystem, and was more heavily influenced by technologies such as PHP and Ruby on Rails. After all, Play was not written for Java EE developers: Play was written for web developers.

    For example, Play 1.0 was influenced by Ruby on Rails’ project structure and user experience, which emphasised a standard pattern for getting started and having things just work. This makes a big difference to developer productivity; the opposite extreme sees teams using JavaServer Faces (JSF) spend days to ‘start-up the project’, with no two JSF applications structured the same way.

    Moving on

    Two years later, Play 1.2 has become so popular that it’s making Java developers who use other web frameworks look bad, because their productivity is so low. This is a good thing, because non-Java frameworks have already been doing this for years. Perhaps there is still hope for Java - as a language, a platform and a culture - to embrace the web and avoid being left behind. Until this happens, Play isn’t a Java web framework: Play is a web framework.

    Conclusion

    Java’s design and evolution seems to be based on the idea that the platform itself is more important than other systems that it might be used with. From a Java perspective, the web is just another external system. As with other APIs, the Servlet API has shielded Java EE from being infected by the web’s own architecture by abstracting it away into a more Java-like API. This approach is unfortunate, because the web is more important than Java - the platform and the language - and these days, a useful web framework is one whose architecture embraces the web’s, and whose API embraces HTTP.

    No programming language is an island. Not even Java.

    Read the original post…

    Semi-synchronicity: Deferred downloads based on time Published November 15, 2011 on Objectify

    Hmm, another blog entry on the Play framework. You must be sooo surprised!

    Play allows you to suspend requests while doing heavy computation – this frees up your application to continue processing new requests, regardless of how long the computation takes. However, you may be deploying to an environment with a fixed request timeout – in the case that prompted me to come up with this code, I was deploying to a server that required requests to return within 120 seconds.

    When generating PDFs, Excel files, images or whatever, that may take longer than the available window I needed to be able to push the computation into the background using a job. This solves the immediate problem, but leads to another issue – what if the job actually completes in a couple of seconds? I would then be forcing the user to then go to another link to download the generated content. Not so good for the user experience.

    A third way was clearly needed, and this is the solution I came up with:

    • All file generation computation runs in a job. This job is responsible for saving the content into the database.
    • A promise is requested from the job, and given a certain amount of time to complete in:
      F.Promise promise = downloadJob.now();
      UserContent userContent = promise.get(5,
                                                            TimeUnit.SECONDS);
      
    • If the object returned from the promise is not null, it’s sent to the browser. If it is null, a message is returned to the browser indicating the generation is on-going.
      if (userContent != null)
      {
          ...
          renderBinary(new ByteArrayInputStream(userContent.content.byteContent),
                            userContent.fileName,
                            userContent.content.byteContent.length,
                            MimeTypes.getMimeType(userContent.fileName),
                            false);
      }
      else
      {
          flash.success("Content is being generated in the background");
          index();
      }
      
    • A download manager is provided to download any generated content generated (even content that returned a binary response).
    • A job returns every night to remove any generated content older than a week
    • The result is an application that will guarantee to return within the alloted timeframe, and also allows users to keep working while their content is generated asynchronously. It also reduces concurrent load on the server because the generation job is executed from within the jobs pool, which can be limited using the application.conf.

      An example implementation can be found here: variable-downloads. The only thing missing (apart from comments – it’s pretty self-explanatory) is polling of the server to update the downloads table when a new download is available.

      Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
      • Digg
      • del.icio.us
      • StumbleUpon
      • DZone
      • Reddit
      • Facebook
      • Google Bookmarks
      • Slashdot
    Read the original post…

    Play framework meet-up at Devoxx Published November 11, 2011 on Lunatech Research

    The Lunatech team will be at Devoxx 2011 next week. We think this is the perfect opportunity to organise a Play framework meet-up at the same time.

    So if you want to talk about Play and meet other players, please join us:

    • Where: AXXES Café - Metropolis, Antwerpen (next to the Devoxx venue)
    • When: Thursday 17 of November, starting at 20:00

    See you there...

    Lunatech Network

    Read the original post…

    December Play!ground in Rotterdam Published November 8, 2011 on Lunatech Research

    Following a break for Devoxx and busy projects, we are now planning the next Play Framework event, for software developers and technical managers.

    This event is the perfect opportunity to learn practical techniques, learn more about Play’s advanced features and meet other Play developers. We also expect to have some fun.

    Details

    Programme

    This event will focus on Play 2.0, with presentations by Peter Hilton and Nicolas Leroux:

    • 16:30 - TBD
    • 17:15 - break
    • 17:30 - TBD
    • 18:15 - drinks, networking

    The programme will combine Play project news and announcements from Devoxx with a technical deep dive on how Play 2.0 works.

    As always, beer and networking are an essential part of the programme.

    Registration

    Register for this event.

    Read the original post…

    Deadbolt – wtf was I thinking? Published November 5, 2011 on Objectify

    I just re-read my previous post and thought to myself…huh? What’s the point in telling people who’ll probably never even read the blog to make sure they cache in order to improve performance?

    The answer came to me in a blaze of comprehension – add a caching feature to Deadbolt, document it and then it’s obvious (to anyone who RTFM of course).

    So, Deadbolt 1.4.3 is released tonight with caching. It should also have been the release with FastTags instead of Groovy tags, but that’s a bug for another day. Now it’s just a question of getting time to finish the Scala version – coming soon :)

    Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
    • Digg
    • del.icio.us
    • StumbleUpon
    • DZone
    • Reddit
    • Facebook
    • Google Bookmarks
    • Slashdot
    Read the original post…

    Play Framework Multiple Clusters Deployment with Capistrano Published November 2, 2011 on Felipe Oliveira

    Post image for Play Framework Multiple Clusters Deployment with Capistrano

    Capistrano is a Ruby-based deployment tool that you’ve probably heard about unless you’ve been living under a rock these past few years. There are plenty of Capistrano-specific tutorials and blog posts out there so I won’t waste your time with that. BUT, there’s not a lot of information regarding deployment for Play Framework applications and nothing specifically for Capistrano other than the documentation provided by the module.

     

    Here are two useful links I got out of the documentation:

     

    • First of all, let’s install Capistrano—that’s easy!

    gem install capistrano (you might have to sudo that depending on your local setup)

     

    • Just to make sure the installation occurred correctly, run “cap -V”. You should see something like this come up:

    Capistrano v2.9.0

     

    • Now let’s add the dependency to the Capistrano module developed by my friend Pascal (@mandubian on Twitter) who’s also the developer behind Siena. Open up conf/dependencies.yml and add the following:

    - play -> capistrano 1.0.0

     

    • Time to tell Play to import the module into your application, so execute the following (and don’t you worry! nobody will have to modify hundreds-of-lines-long pom.xml file!):

    play dependencies

     

    • Let’s add support to multiple stages to Capistrano! First execute “gem install capistrano-ext”. Then add the following lines to the very top of conf/deploy.rb:

    require 'capistrano/ext/multistage'
    set :stages, %w{staging production}
    set :default_stage, "staging"

     

    • Now create a configuration file for each enviroment:

    config/deploy/staging.rb
    role :web, "staging1", "staging2"

     

    config/deploy/production.rb
    role :web, "prod1", "prod2"

     

    • Now you need to input some information on conf/deploy.rb so Capistrano knows about your SCM setup, etc. This is what it should look like:

    set :application, "Felipe Oliveira Play Framework App"

    set :repository,  "git@github.com:feliperazeek/myproject.git"

    set :scm, :git

    set :deploy_to, "/opt/felipera_app"

    set :play_path, "/opt/play"

    ssh_options[:forward_agent] = true

    set :branch, "my_release_branch_1234"

    set :shared_path, "#{deploy_to}/shared"

    set :app_pid, "#{shared_path}/pids/server.pid"

    set :app_path, "#{deploy_to}/current"

    set :user, "felipera"

     

    • And finally … Dream Roll please …

    cap staging deploy

     

    • … Or Better Yet!

    cap production deploy

     

    The module provides more functionality than that. You can always visit the documentation; I don’t want to bore you repeating all that.

    Pascal keeps rolling out the goods!

     

    Enhanced by Zemanta

    Read the original post…

    Progress bars with jQuery UI, WebSocket & Play Published October 31, 2011 on Lunatech Research

    This article shows you how to use a jQuery UI component and Web Sockets to implement a progress bar for a deterministic asynchronous server-side job in a Play framework web application. This is an example of a user-interface component that is not part of the web’s stateless request-response paradigm, but is now possible with new HTML5 features.

    This follows on from earlier jQuery UI component articles: jQuery UI Ajax autocomplete with Play, Lazy loading page content with jQuery UI, Ajax and Play and Selector dialogue with jQuery UI, Ajax and Play. The examples and source code for all of these articles are available as part of the Play framework jQuery UI module.

    For this example, we are going to start a long-running job in our web application on the server, and display progress in real-time:

    Progress bar example

    Note that this time we are not using a time zones example, although the recent time zone database debacle seems to have been largely resolved.

    Architecture

    The Architecture of the World Wide Web is about resources and their identifiers and representations, and while we are used to the original web of HTML documents and URLs, resources and representations can be richer. The key resource in this progress bar example is a server-side process.

    The Play framework includes support for starting asynchronous server-side jobs - processes that continue running outside the scope of the HTTP request-response cycle. This is useful for important tasks that must be completed independently of the user’s navigation behaviour, such as sending hundreds of party invitation e-mails. The challenge with these long-running jobs is to use URIs to identify them as ‘resources’ in the web architecture sense, and to provide useful representations.

    For this example, we will use a web socket URI to address an asynchronous job, and on the server-side generate a representation consisting of only a single number - the job’s completion percentage. Play’s web sockets support is ideal for updating the progress bar, and Play’s asynchronous jobs are suitable for long-running jobs.

    Note that web sockets support on both server-side and client-side is still evolving. This example works with Play 1.2.3 and Safari 5.1.1; Play 1.2.4 adds Chrome support.

    Progress bar

    The jQuery UI progress bar widget shows progress for a server-side process for which the completion percentage can be calculated. Progress bars are useful for processes that take longer than a few seconds to complete, provided that they are deterministic, i.e. processes whose progress can be measured or predicted.

    Client

    The widget is based on an empty HTML div element.

    <div id="progressbar" data-url="@@{jqueryui.ProgressSocket.progress(processId)}"></div>
    

    The data-url attribute value specifies the URL for a web socket connection. Note that the template uses the @@ syntax to generate an absolute URL that includes the web socket protocol - ws://localhost:9000/progressbar/progress.

    The progressbar.js JavaScript applies the jQuery UI dialog plug-in to the div element and opens a web socket connection. Finally, the JavaScript uses web socket messages to update the progress bar value.

    $(function() {
    
       // Initialise the progress bar.
       var $progressbar = $('#progressbar').progressbar();
    
       // Open the web socket connection.
       var serverUrl = $progressbar.data('url');
       var socket = new WebSocket(serverUrl);
    
       // Use web socket messages to update the progress bar.
       socket.onmessage = function(event) {
          $progressbar.progressbar('value', parseInt(event.data));
       };
    });
    

    Server

    The server-side has three parts. First, we define an implementation of a long-running job, which has a generated UUID identifier and an event stream that the job will publish progress to. The implementation in this example simply waits for short intervals, publishing progress to the event stream after each one.

    package models.jqueryui;
    
    import play.jobs.Job;
    import play.libs.Codec;
    import play.libs.F;
    
    import java.io.Serializable;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Example job that publishes progress as an event stream.
     */
    public class Process extends Job implements Serializable {
    
       public static Map<String, Process> registry = new HashMap<String, Process>();
    
       public String id = Codec.UUID();
    
       /**
        * Event stream for events that report job completion percentage.
        */
       public F.EventStream<Integer> percentComplete = new F.EventStream<Integer>();
    
       public void doJob() {
          // Report completion percentage every 100 ms.
          for (int i = 1; i <= 50; i++) {
             try {
                Thread.sleep(100l);
                final int percent = i * 2;
                this.percentComplete.publish(percent);
             } catch (InterruptedException e) {
                // ignore
             }
          }
       }
    }
    

    The second server-side class is a conventional action that starts an asynchronous long-running job, and stores a reference to the job in a ‘registry’ singleton. This action then renders the same page with a processId argument that indicates that a job has been started.

    package controllers.jqueryui;
    
    import models.jqueryui.Process;
    
    /**
     * Progressbar example.
     */
    public class Progressbar extends JQueryUI {
    
       /**
        * Start a job, cache it and re-render the page
        */
       public static void startJob() {
          final Process process = new Process();
          process.now();
          final String processId = process.id;
          Process.registry.put(processId, process);
          renderTemplate("jqueryui/Progressbar/index.html", processId);
       }
    }
    

    The last part is a web socket controller that retrieves the running job from the registry, using its ID, and waits for events on the job’s event stream. When the job publishes a completion percentage to its event stream, the controller sends the data in a web socket message to the browser client.

    package controllers.jqueryui;
    
    import models.jqueryui.Process;
    import play.libs.F;
    import play.mvc.Http;
    import play.mvc.WebSocketController;
    
    import static play.libs.F.Matcher.ClassOf;
    
    /**
     * Web socket controller for use by the progress bar.
     */
    public class ProgressSocket extends WebSocketController {
    
       public static void progress(final String processId) {
    
          final Process process = Process.registry.get(processId);
          final F.EventStream<Integer> progress = process.percentComplete;
    
          // Loop while the socket is open
          while (inbound.isOpen()) {
    
             // Wait for either an inbound socket event or a process progress event.
             F.Either<Http.WebSocketEvent, Integer> e = await(F.Promise.waitEither(
                inbound.nextEvent(),
                progress.nextEvent()
             ));
    
             // Case: The socket has been closed
             for (Http.WebSocketClose closed : Http.WebSocketEvent.SocketClosed.match(e._1)) {
                disconnect();
             }
    
             // Case: percentComplete published - send the value to the client.
             for (Integer percentComplete : ClassOf(Integer.class).match(e._2)) {
                outbound.send(percentComplete.toString());
                if (percentComplete >= 100) {
                   disconnect();
                }
             }
          }
       }
    
    }
    

    Note that this design means that the job is started by a conventional HTTP POST request to the Progressbar.startJob() action, which means that the job is executed even if the client does not have web socket support and is therefore unable to update the progress bar.

    One possible enhancement would be to add JavaScript to detect the case where web sockets are not supported, and send a single Ajax request to get the current progress value to update the progress bar.

    Conclusion

    Web sockets are an HTML5 technology that you can now use in your web applications, thanks to browser support for the JavaScript API and Play’s server-side support. This is good news for developers who can see opportunities to improve user-experience in their applications with more sophisticated applications.

    Peter Hilton is a senior software developer at Lunatech Research and committer on the Play open-source project.

    Read the original post…

    Deadbolt – make sure your Play! framework app’s security is efficient Published October 27, 2011 on Objectify

    If you’re using Deadbolt to provide authorisation support for your Play! app, you need to be aware that DeadboltHandler#getRoleHolder() can potentially be called a lot due to the template tags. A rule of thumb is that for every #{restrict} or #{restrictedResource} tag in your template, getRoleHolder() will be invoked once. If you’re hitting the database to get the user every time, this can have a huge impact on your performance.

    Since it’s likely that the your RoleHolder won’t change within a request, you should consider adding the RoleHolder instance to the request argument if you’re not already storing it for the lifespan of the request!

    Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
    • Digg
    • del.icio.us
    • StumbleUpon
    • DZone
    • Reddit
    • Facebook
    • Google Bookmarks
    • Slashdot
    Read the original post…

    RivieraDEV - the official pictures Published October 25, 2011 on Lunatech Research

    Thanks to Nicolas Martignole I can now show some pictures from the RivieraDEV event.

    Nicolas Leroux is is a solution architect and technical director at Lunatech.

    Read the original post…

    Lunatech at the RivieraDEV Published October 24, 2011 on Lunatech Research

    I just came back from RivieraDEV, located on the French Riviera. Lunatech sponsored this nice and sunny conference. There were load of good talks and Nicolas Martignole and myself - the Nicolases ™ - gave a presentation about Play! framework with some really nice demos. One of the demo showed a video chat.

    RivieraDEV

    The presentation's video should be available pretty soon, stay tuned!

    Highlight of the conference were probably the Coffeescript presentation by Bodil Stokke and the Github presentation by Zach Holman. I hope to be invited next year - this year was easy since I helped organised the conference ;). Big thanks to Stephane, Yannis and all the RivieraDEV team.

    Play framework presentation slides

    Our presentation is available here: Play! Framework: To infinity and beyond (PDF).

    PS: I left my phone in Rotterdam, so although it was nice and quiet, I did not get any pictures of the event.

    Nicolas Leroux is is a solution architect and technical director at Lunatech.

    Read the original post…

    Play Hackathon Published October 16, 2011 on Wayne

    Get Hacking!

    Inspired by the National Novel Writing Month (NaNoWriMo), this competition is aimed at teams of Play developers to produce awesome applications during the month of November. At the end of November, the finished applications will be judged (by the Play Community) to see who has the best application, and which team has won.

    Rules

    • Start developing 1st November 2011
    • Finish developing 30th November 2011
    • Judging will start 1st December for 1 week
    • Winners will be announced 8th December
    • Teams up to 5 members
    • Your application must have an about page, or popup, stating it was developed as part of this event and using the Play Framework

    Sponsors and Prizes

    If you would like to be a sponsor, or donate prizes for this event, please get in contact with me.

    Register
    To sign up and register for the event, just go along to the Registration page, hosted on Heroku.

    I will post another short blog later this week on how simple it was to get up and running on Heroku.


    Read the original post…

    How to deploy your play applications on ArchLinux with daemons Published October 15, 2011 on GreWeb

    This video shows how to run different instances of Play framework server in the most Linux friendly way: using daemons. Example with ArchLinux, using yaourt, the playframework AUR package and nginx.

    Some links

    Abstract summary

    Introduction

    Existing Platform as a Service: Playapps.net, Heroku.com.

    Our needs are quite different: you sometimes need to have your own server on your own infrastructure and not depending on third party web services.

    Let’s see how to deploy some play applications from scratch with ArchLinux.

    Requirement

    Install ArchLinux on your server

    Install yaourt

    Installation

    yaourt -S playframework

    Creating 2 play framework applications

    mkdir sites && cd sites
    play new app1
    play new app2 # + editing app/views/

    Configuring daemons

    cd /etc/rc.d
    ln -s skeleton_playapp app1
    ln -s skeleton_playapp app2
    cd /etc/conf.d
    cp playapp_sample app1
    cp playapp_sample app2
    vim app1 # configure variables
    vim app2 # configure variables

    For app1 :

    PLAY_APP=/home/gre/sites/app1
    PLAY_USER=gre
    PLAY_ARGS="--%prod --http.port=9001"

    For app2 :

    PLAY_APP=/home/gre/sites/app2
    PLAY_USER=gre
    PLAY_ARGS="--%prod --http.port=9002"

    Starting daemons

    rc.d start app1
    rc.d start app2

    Make it permanent in /etc/rc.conf by adding them in the DAEMONS variable.

    ...
    DAEMONS=(... app1 app2)

    Nginx, as a front end proxy server

    Install nginx using pacman.

    Edit /etc/nginx/conf/nginx.conf

    ...
        server {
            listen 80;
            server_name app2.archdemo;
            location / {
              proxy_pass http://127.0.0.1:9002;
              proxy_set_header Host $host;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header X-Forwarded-Host $host;
              proxy_set_header X-Forwarded-Port $server_port;
              proxy_set_header X-Forwarded-Proto https;
            }
        }
        server {
            listen 80;
            server_name app1.archdemo;
            location / {
              proxy_pass http://127.0.0.1:9001;
              proxy_set_header Host $host;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header X-Forwarded-Host $host;
              proxy_set_header X-Forwarded-Port $server_port;
              proxy_set_header X-Forwarded-Proto https;
            }
        }
    ...

    flattr this!

    Read the original post…

    Add funkier feedback to your Play! apps Published October 12, 2011 on Objectify

    Providing feedback to users following some action is important if you don’t want them confused or – worse – annoyed with your application. You can achieve this by adding something to the view following every action, but the question is where? If you add, for example, the information in a div at the top of your page this is noticable but can only contain so much information before you start screwing up your carefully designed page layout.

    Another option is to use dialogs – you can get a lot of information in them and they won’t affect your page payout – but they’re a) annoying and b) blocking if modal.

    A third option is to use a notification widget, and that’s what this example does. I’ve chosen Eric Hynds’ excellent jquery.notify plugin – it’s small, fast and easily configurable. Take a look at the demos at http://www.erichynds.com/examples/jquery-notify/ to get a feel for them.

    Due to the inheritable structure of Play! views, you can define the entire setup of the notification system in your root view and have it automatically handle success or error messages from your flash context. For notifying of AJAX results, a small utility method can handle the dispatch to the correct notify method.

    To get started, you’ll need to have jquery and jquery-ui in your application. Add the javascript and css to your root view (e.g. app/views/main.html)

    <link rel="stylesheet" type="text/css"
              href="@{'/public/javascripts/jquery-ui/css/ui-lightness/jquery-ui-1.8.16.custom.css'}" charset="utf-8">
    <script src="@{'/public/javascripts/jquery-1.5.2.min.js'}"
                  type="text/javascript" charset="${_response_encoding}"></script>
    <script src="@{'/public/javascripts/jquery-ui/js/jquery-ui-1.8.16.custom.min.js'}"
                  type="text/javascript" charset="${_response_encoding}"></script>
    

    Next, head on over to https://github.com/ehynds/jquery-notify and download the latest version of jquery.notify. Put the .js and .css files in your favoured locations, and reference them from your root view:

    <link rel="stylesheet" type="text/css"
              href="@{'/public/stylesheets/ui.notify.css'}" charset="utf-8">
    <script src="@{'/public/javascripts/jquery.notify.js'}"
                  type="text/javascript" charset="${_response_encoding}"></script>
    

    Next, we need to hook the widget into the view. In the body tag of your root, add the following above the doLayout tag:

    <div id="notifyContainer">
        <div id="notifyPopup">
            <a class="ui-notify-close ui-notify-cross" href="#">x</a>
                <div style="float:left;margin:0 10px 0 0"><img src="${'#'}{icon}" alt="${'#'}{notificationType}"/></div>
                <h1>${'#'}{title}</h1>
            <p>${'#'}{text}</p>
        </div>
    </div>
    

    Notice one oddity here – because the templating used by the notify plugin conflicts with Play’s syntax, we have to twist things a bit. Instead of writing, for example, src=”#{icon}” we have to use src=”${‘#’}{icon}”. This will write the literal # into the resulting HTML, and match what notify expects without causing a server-side exception from Play’s rendering engine.

    Now it’s time to time to add the javascript support that will do the heavy lifting. This goes into the head of your root view, and consists of three things:

    • Globally-available functions that allow the notifications to be invoked from anywhere (including iframes)
    • A document-ready block that prepares the notification widget for use
    • A hook-up for Play’s flash context

    See the in-code comments for an explanation of what’s what. Comments use the Play comment syntax of *{}*

    <script type="text/javascript">
        *{ Creates the notificaton popup with the given message, icon, etc.  All other methods are convenience methods for this. }*
        function createNotification(notificationContainer, template, vars, opts) {
            return notificationContainer.notify("create", template, vars, opts);
        }
    
        *{ Convenience method for notifying on AJAX results.  See the AjaxResult class in the downloadble example below for the structure of the result parameter }*
        function ajaxNotify(result) {
            if (result.success) {
                notifySuccess(result.message);
            } else {
                notifyError(result.message);
            }
        }
    
        *{ Convenience method for creating success dialogs }*
        function notifySuccess(message) {
            createNotification($notifyContainer,
                                       "notifyPopup",
                                       { title:'Success',
                                         text:message,
                                         icon:'@{'/public/images/cool-icon.jpg'}',
                                         notificationType: 'Success'},
                                       {expires:10000});
        }
    
        *{ Convenience method for creating error dialogs }*
        function notifyError(message) {
            createNotification($notifyContainer,
                                       "notifyPopup",
                                       { title:'Error',
                                         text:message,
                                         icon:'@{'/public/images/shame-icon.jpg'}',
                                         notificationType: 'Success'},
                                       { expires:false });
        }
    
        *{ Runs when the document is ready }*
        $(function() {
            *{ Prepare the notification widget }*
            $notifyContainer = $("#notifyContainer").notify();
    
            *{ Create notifications if there is a success or error to report on }*
            #{if flash?.success}
                notifySuccess('${flash.success}');
            #{/if}
            #{if flash?.error}
                notifyError('${flash.error}');
            #{/if}
        });
    </script>
    

    Note the images used here can be anything – just put something in your public/images directory and reference it here.

    And that’s it! If you have success or error states in your flash, they’ll automatically pop up when the page loads. In the example above, success messages stick around for 10 seconds and then vanish, but error messages have to be manually closed.

    As for AJAX calls, you simply need to add a callback function to the call that will invoke the correct method when the call returns. If you call renderJSON() from your controller on an instance of AjaxResult (see the example download), you can use the ajaxNotify() method with the JSON object and it will route to the correct notification automatically.

    For example,

    $.post('@{Application.ajaxSomethingSuccessful()}',
              function(result) {
                  ajaxNotify(result);
              });
    

    You can download the implementation here: notifications. Note that it’s quite a large file because the whole JQuery UI library is included.

    Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
    • Digg
    • del.icio.us
    • StumbleUpon
    • DZone
    • Reddit
    • Facebook
    • Google Bookmarks
    • Slashdot
    Read the original post…

    Client Certificates and Play! Published September 30, 2011 on Hugo Monteiro

    Sometimes we need the authentication of the client. That means, for instance, if you want to limit the access to your web application, from the people who has the right certificate.
    This is possible, using client certificates, which are installed inside the browser, and the user without this certificate cannot access the web application.

    To create client certificates, you need to check if you have openssl installed. After this verification, you need to find where the auxiliary command CA and/or CA.pl is installed. On my Mac  it’s located in “/System/Library/OpenSSL/misc/CA.pl“.

    1. First, we need to create a Certificate Authority (CA):

    $ CA.pl -newca

    After pressing enter, and following some instructions, a new folder “demoCA” is created with our newly created Certificate Authority.

    2. Create a certificate signing request:

    $ CA.pl -newreq

    Follow the instructions to create the certificate signing request. Two files will be created: “Request is in newreq.pem, private key is in newkey.pem“.

    3. Sign it with the CA:

    $ CA.pl -sign

    The signed certificate newcert.pem is generated.

    4. Create a client certificate that our user will install in his browser:

    $ openssl pkcs12 -export -inkey newkey.pem \
               -in newcert.pem -out clientCertificate.p12

    As we can see, we use the private key newkey.pem and the CA signed certificate to create the client certificate.

    Now that we have all the certificates created we need to use a tool to save our Certificate Authority that will be verified when someone asks for authorization with a certificate. I prefer to use the “keytool“. Verify that you have keytool command available before you begin:

    5. Create a keystore:

    $ keytool -genkey -keystore truststore.jks

    6. Add CA to keystore

    $ keytool -import -trustcacerts -alias "my CA" \
                    -file demoCA/cacert.pem -keystore truststore.jks

    7. Configure Play! Framework:

    Add to the  application.conf file, the keystore configurations:

    play.netty.clientAuth=need
    keystore.algorithm=jks
    keystore.file=conf/truststore.jks
    keystore.password=mykeystorepassword

    Conclusions:

    Inside the keystore, there is the Certificate Authority that will be verified when the client tries to comunicate with the server, using a certificate signed by the CA. This is very helpful if you want to build a web application that is in the Internet, and you just want the people from inside the company to access to it. Off course, the disadvantage of this approach is that if your user steals the certificate, he also can access the application everywhere.

    References:

    Read the original post…

    Step-by-Step for a Simple Twitter with Play Framework, AJAX, CRUD and Heroku Published August 30, 2011 on Felipe Oliveira

    Post image for 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)
  • <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

    GET /rest/tweets Application.tweets

     

  • 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!

    Read the original post…

    Why Did I Fall in Love with Play! Framework? Published August 25, 2011 on Felipe Oliveira

    Play Framework - Felipe Oliveira

    Some time ago, I was the tech lead for a few very large deployments on the Real Estate market for companies like Fannie Mae, Freddie Mac, Foreclosure.com and HUD. We were running that traditional enterprise Java stack you are probably familiar with—Spring, Hibernate, Solr, etc. It took a few years but we had built a very nice system; it performed well but deep inside I felt development wasn’t as productive as it should have been. I also noticed that the whole dev process wasn’t as fun as it used to be. Of course, I had heard a lot of great stories about Rails, Django and, more recently, Node.js; there were actually some compelling stories surrounding those technologies. I ended up spending a fair amount of my spare time working on those technologies, and I actually had a really great time building some small apps and prototypes with them. But then I would wake up the next morning, go to work, face another big important project and go right back into my tried and true: Java. 

    One of those projects was an online offer management system for Fannie Mae which was to receive a billion dollars in offers in its first month. In my mind, there was no way I would introduce a brand new language—especially a scripting language like Python or Ruby—to the team for such an important project. From personal experience, I feel it’s difficult to manage a large project without type checking. I was basically between a rock and a hard place because I wasn’t very excited about the options in the Java space, and I had only a very modest level of success with the other alternatives like Grails, Spring Roo, etc. At the same time, I wasn’t about to give up on Java as a language, especially on the JVM which I grew to trust because of its reliability. 

    Then I ran into Play; it was love at first sight for me. (I’d love to tell you how I ran into Play … just follow me on Twitter—[@_felipera] so I can beat Justin “Beaver”‘s Klout score!) Once I decided to take it for a ride, I was up and running right away! With a simple command, “play new”, the whole application structure was defined. Follow that with another simple command, “play run”, and I was ready to get the party started! I felt instant relief because I didn’t need to come up with all those XML files, Spring’s applicationContext.xml, the web.xml, Hibernate’s HBM files, and THEN figure out how to wire them all together! Even after years working on those technologies, I still had to copy and paste them from somewhere; I could never remember all that syntax. 

    Another obvious compelling point for me was Play’s ability to reload classes on the fly without having to re-deploy the entire application or restart the server. I think we all know what it’s like to be working on an application, make a change to a class, execute maven or ant deploy … wait until a war is packaged … copied to a deploy directory … wait for the servlet context to get destroyed … then wait some more for the application to be deployed. And THEN … once the application is FINALLY deployed, we open the browser, hit our development environment and THERE’S A BUG! The problem could be as simple as a single character misplaced somewhere. It doesn’t matter what the problem is, we still need to go over that entire process all over again. By the third or fourth time that happens, the developer zones off on Slashdot, Hacker News or whatever his/her favorite website is. Play handles class reloading beautifully; you really don’t have to restart your server!

    I was also attracted to Play’s Stateless model, that “Share Nothing” HTTP architecture. Many of us were unfortunate enough to have developed, and even worse, supported J2EE-based applications that were built on a Stateful model. It was really hard managing state, cluster-safe cache objects, HTTP sessions, especially for those Enterprise Java Beans (EJBs) and that whole concept of attached objects. Play doesn’t share state between each node which simplifies the management of your cluster, and it provides a cluster-aware and cluster-safe caching solution.

    Man, I could go on and on all night but I’ll spare you from all my craziness! In a nutshell, Play is a full stack framework for modern Web applications with a NIO-based development and production servers, full support for MVC, a persistence engine, a fully integrated testing framework (unit testing and functional testing), a powerful async Web Service client, an async-based job manager, multiple extensions are available through modules, support for full customization on the framework behavior through its plugin mechanism, dependency management, validation framework and even more advanced features such as WebSockets.

    I don’t know if you guys know this but I’m an old man; I’ve been developing Web applications for 15 or so years now. And for the most part, with undying passion. But Play has rejuvenated my love for developing Web applications all over again. 
     
    This is—more than anything—a declaration of love,
    Felipe Oliveira

    Now Go Play!

    Read the original post…

    Hidden Features of the Play Framework Routes File Published July 15, 2011 on Wayne

    Background

    Today, an interesting question was raised at Stackoverflow regarding if it were possible to define Dev/Prod mode specific routes in the Routes file.

    The simple answer, was that I didn’t know, but I had an theory that this could be possible, so I threw together a quick prototype to see if it would work.

    The premise of the idea was that the routes file does allow scripting to take place, which I have used before to define a Context, which is the agreed way to for managing the war context when deploying to Tomact and other Servlet containers.

    So, taking the idea that scriptlets are possible in the routes file, I wondered if this could be taken a step further, whereby logic could be carried out in the routes file, rather than simple assignment scriptlets.

    The prototype

    The prototype itself was pretty simple. I started a new play project

    play new routesproto

    and started the Play server.

    play run routesproto

    I then modified the Application.java to have a few actions, which simply returned a little text to show the action completed successfully. There was simply no need to write templates for the actions, as that was not what I wanted to prove.

    public class Application extends Controller {
    
        public static void index() {
            render();
        }
    	
        public static void noDev() {
            renderText("NoDev");
        }
        public static void noProd() { 
            renderText("NoProd");
        }
    }
    

    I then went about making my routes file Dev and Prod specific. I created a few routes per environment as follows.

    
    # Home page
    GET     /                                       Application.index
    
    # Ignore favicon requests
    GET     /favicon.ico                            404
    # Map static resources from the /app/public folder to the /public path
    GET     /public/                                staticDir:public
    
    %{ if (play.mode.isProd()) { }%
    GET		/route1									Application.noDev
    GET		/route2									Application.noDev
    GET		/route3									Application.noDev
    %{ } }%
    
    
    %{ if (play.mode.isDev()) { }%
    GET		/route4									Application.noProd
    GET		/route5									Application.noProd
    GET		/route6									Application.noProd
    %{ } }%
    
    *       /{controller}/{action}                  {controller}.{action}
    

    So, what’s going on in here? Well, all the main (shared) routes are held at the top of the routes file, and then anything that becomes specific to Dev or Prod mode are placed at the bottom. As usually is the case, the catch-all should be last, so after the second if tag is closed, we follow it with the catch-all route.

    The following line is responsible for the logic in our routes file.

    %{ if (play.mode.isDev()) { }%

    and all routes between this piece of logic, and the closing of the if statement, indicated by the following line, are enabled.
    %{ } }%

    This simple line simply checks what Mode the application is running in, and if it is running in Dev mode, then the routes defined in between the opening and closing parenthesis become available.

    Conclusion

    I do not expect this syntax to immediately find its way in to every Play application routes file, but I no doubt think that it will be useful to many of us Players. Indeed, without the Stackoverflow question, I would never have even considered experimenting whether this method was actually possible or not, so thanks to Roshan for raising the question.


    Read the original post…