CSC/ECE 517 Fall 2014/ch1a 1 sj

From Expertiza_Wiki
Revision as of 21:39, 19 September 2014 by Jlourde (talk | contribs)
Jump to navigation Jump to search

Play Framework is a high velocity web development framework for Java and Scala. It uses the Model-view-controller (MVC) architectural pattern for implementing user interfaces. Play is based on a lightweight, stateless and web-friendly architecture written in Scala. The primary goal of Play framework is to provide a developer friendly development platform for web development.

The major advantage of Play over other Java EE frameworks is its ability to build highly scalable applications. Its reactive model (Reactive Manifesto), thanks to Iteratee IO provides nominal consumption of resources (CPU cores, memory), a major requirement for ascendable and asynchronous applications.

Some of the major companies that use Play framework are LinkedIn, Klout, TheGuardian, ZapTravel and GILT

Motivation

  • To create a stateless web framework

Traditional web frameworks are stateful and because of this scalability becomes an issue after a while. The creators of the Play framework found that stateless frameworks are more stable when there is higher traffic since no overhead is incurred in tracking and maintaining user state information.

  • To have an ‘evented’ web server architecture as opposed to a ‘threaded’ web server architecture

Since the Play framework is essentially stateless, an event driven web server architecture was more appropriate to base Play on than modelling it as threaded. Therefore, it was decided to base play on Netty – an event-driven client-server framework.

  • To provide full-stack web framework

The creators of the framework wanted to provide developers with a single complete framework that was capable of model-persistence and which had template (view), controller and testing mechanisms. In Play, model and controller can be realized with Java and Scala, views are realized with a template syntax and Scala and model persistence is done with Ebean by default with the option to use any other persistence mechanism. JUnit, Selenium WebDriver and FluentLenium are mainly used as the testing tools for Play.

  • To provide a developer friendly feature driven framework

One of the primary motivations of the Play framework was to make development as easy as possible for the developer. To do this features such as hot reload (mimicking interpreted languages), integration to JSON and integration of compilers for CoffeeScript, LESS etc. were provided. Development on Ruby on Rails and Django is fairly simple and the creators of Play wanted to mimic this and hence modeled Play on these frameworks. Play is also fully compiled, typesafe, RESTful by default and provides support for long living connections(WebSocket, Comet etc).

Features of Play Framework

  • As mentioned before, Play is a stateless, light weight framework which is very flexible. The MVC architecture inherently provides flexibility but along with this there are many elements in Play which are pluggable, configurable or customizable.
  • Play makes use of Akka which supports multiple programming models for message based asynchronous concurrency. As a result of this, even large scale applications built on Play consume minimum resources in terms of CPU, memory and threads.
  • Another advantage that Akka provides to Play is predictable scalability. The asynchronous model of Akka coupled with the stateless, non-blocking I/O nature of Play ensures that there are no hiccups while scaling up.
  • Development on Play is simple and straight forward. Owing to features such as hot reload, powerful console & build tools, type safety, built in testing tools and IDE support for Eclipse & IntelliJ IDEA all that is required for development would be a browser and a text editor. This enhances the productivity of developers dramatically.
  • Play provides many features for modern web and mobile app development. Being RESTful by default, integration for JSON and compilers for CoffeeScript, Less etc., support for protocol technologies such as WebSocket & Comet and extensive NoSQL & Big Data support are just some of these features.
  • The reactive nature of Play is another important feature. Apps developed based on a Service oriented architecture would require multiple parallel asynchronous requests to be sent out. Netty supports non - blocking I/O and hence it is not expensive to make such calls.
  • Play is open source which allows for evaluation of the underlying code and also facilitates monitoring of the framework code. There is also a large user community who contribute libraries and help clarify the doubts of fellow users. But, even though play is open source, there is an option to receive commercial support.
  • Play provides a developer friendly error handling mechanism where the error is directly mentioned in the browser itself with the file path, line number as well as the relevant code. This saves a lot of developer time and effort since he/she would not have to dig through and analyze large log files.

History

The early versions of Play framework can be traced back to early 2007 while it was being developed at Zenexity by software developer Guillaume Bort. The first full version of Play was in October 2009. Later in 2011, Sadek Drobi, co-creator of Play, joined the Play development wagon to release Play 2.0 in conjunction with Typesafe Stack 2.0.

Release History

Release Version Date of Release Features
Play 1.x November 2010 - April 2011
  • Native Scala Support
  • Migration from Apache MINA to JBoss Netty
  • OAuth and HTTPS support
Play 2.0 March 2012
  • Native Support for Java and Scala
  • Asynchronous programming support by inclusion of WebSockets and Comet
  • Built-in relational database access libraries such as Ebean, JPA and Anorm
Play 2.1 Februrary 2013
  • Migration to Scala 2.10 API
  • RequireJS support
  • New Scala JSON API
Play 2.2 September 2013
  • Improved Java Promise API
  • SBT 0.13 support
  • Built in Gzip support
Play 2.3 May 2014
  • Introduced Activator command
  • Support for Scala 2.11
  • Custom SSL Engine for HTTPS
  • Upgrade to Netty 3.9.3

Architecture

MVC application model

Play follows a typical MVC architectural design pattern of web application development. This divides the application into two broad layers:

  • The Model Layer: It handles the business logic of the actual domain problem.
  • The Presentation Layer: This can be categorized into two sub parts.
    • The View: It handles the actual GUI of the application
    • The Controller: It maps the actions on the user interface to the concerned models.

The Model refers to the entities involved in the real world domains. It captures the actual data and applies the programming logic to it. The model operates on the raw data and adds "meaning" to it. Generally this data is stored in a persistent storage medium, like a database. Th model interacts with this data by means of a Data Access Layer which is encapsulated by it.

The View refers to the actual Graphical User Interface(GUI) displayed on the browser. This is the interface with which the user connects to the application. The data is inputted into the application using the interface provided by the view. It is usually displayed in the browser using HTML, CSS and JSON formats. It acts as the single point of access to the application for the end user.

The Controller maps the user actions (events) to the concerned models and invokes the required changes in them. It processes the events and affects the behavior of the underlying models. Typically, in a web application, the events generated are HTTP/HTTPS requests. The responsibility of the controller is to act as a filter for the HTTP requests, process them, extract relevant information and pass it to the concerned entities.

A typical MVC architectural design pattern.
MVC architectural pttern.

In a Play application, these three components are placed in the app directory, each in a separate package.

app/controllers

These are the Java classes that receive the HTTP requests. They are extended form the play.mvc.Controller class. Each HTTP request is attached to a action method. This is a public and static method having the following signature:

public static void action_name(params...);

Various parameters can be defined as inputs to the action methods. Play automatically maps them from the corresponding HTTP request parameters. There is generally no limit on the number of parameters to be passed and they can also be sent as query strings.

app/models

These are the Java classes exhibiting typical Java behavior. Unlike the controllers, they follow the Java object oriented paradigm. This package contains the classes that represent the various actors in the use cases. All the corresponding operations pertaining to these actors are contained in the Model classes. The model classes access the data storage mediums to persist and update data.

app/views

This package contains special HTML, XML template files which are used to render the GUI on the user browser screen. The Play templating engine renders these views using special directives contained in these files. The Controller gets the data from the models and uses a template to decorate the views.


Standard Application Layout

The app directory

This directory contains a sub folder for each of the layer in the MVC pattern. This is the directory under which the developers can add their code as well as HTML pages. Apart from the above mentioned packages, developers can create their own packages.

The public directory

This directory contains the static resources which are not modified by the framework. their state remains the same after deployment. These contain the image files, CSS files, JavaScript files.

The conf directory

The conf directory is the directory that imparts the feature of configuration-over-convention to the framework. It contains all the configuration files required by the framework and the application. Two mandatory configuration files are:

application.conf file: This file contains the standard configurations at time of application start up. Play provides a sophisticated API to read values from this file

Play.application().configuration().getString("key");
Play.application().configuration().getInt("number");

routes file: This file contains the configurable URLs. The routes defined here are mapped to controller functions which accept HTTP requests, render views etc.

GET        /home                         Controllers.Application.index(Int ?= 2)
POST       /verifyuser                   Controllers.Login.verifyUser(String username)

Compilation Errors

The Play framework provides a hot deployment functionality. It means that code need not be compiled before deployment on the server. The developer can write the piece of code and directly hit refresh to execute the code. The compilation and execution happens at the time of deployment. Compilation errors, if any, are directly shown on the browser screen.

Compilation Error in play.
A compilation error shown on the browser screen

Since, compilation and packaging happen at the time of deployment, Play does not have an elaborate development cycle. Although, two distinctive server modes are supported by Play. The DEV mode to be used for development purposes and the PROD mode when application is deployed. The main difference between the two modes is that hot reloading is not supported in the production mode.

Miscellaneous

Asynchronous and Scalable programming

The feature that makes Play a preferred framework for asynchronous and scalable applications is the inclusion of Akka toolkit. Instead of doing it the Java way of concurrency using threads, semaphores, and locks; Akka emphasizes upon actor-based concurrency. It implements the Actor model. The actors ,which are built on a fixed number of threads which is configurable, converse by the means of messages generated due to events. This helps Play achieve its scalability without having to handle it programatically. Each actor consists of a mailbox and a queue. The mailbox registers the events and are passed as inputs to the actor. These actors, belonging to an actor system then process the messages and perform the assigned tasks in parallel.

import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
 
public class MyActor extends UntypedActor {
  LoggingAdapter log = Logging.getLogger(getContext().system(), this);
 
  public void onReceive(Object message) throws Exception {
    if (message instanceof String) {
      log.info("Received String message: {}", message);
      getSender().tell(message, getSelf());
    } else
      unhandled(message);
  }
}

The actor can be created by the following line of code below:

ActorRef myActor = Akka.system().actorOf(new Props(MyActor.class));

Also the number of actors initialized at application start up, by specifying a property in the application.conf file.

Backward compatibility

As shown in the History of Releases tab, Play framework got a complete overhaul after Play 2.0 The major difference turns out to be that Play 1.x was in Java while Play 2.x is in Scala. This renders it as backward incompatible. This caused a lot of furor at the time of the release of 2.0 version as there was no portability script provided for migration from 1.x to 2.0. However, it was clearly seen that the advantages of this Scala version far outweighed the problems faced in application porting.

Downsides of Play 1.x

  • Bytecode manipulations
  • Does not follow Java conventions
  • Poor Iversion of Control

Wins of Play 2.0

  • Suited for asynchronous programming
  • Improved and flexible cache support
  • Convenient Data Access Layer for database requests
  • Inclusion of Akka: Actor based, event driven framework

Play vs Java EE frameworks

References