Saturday, September 10, 2011

The Play Framework - Part 3

The Play Framework is a MVC web application framework for Java that focuses on being light-weight and easy to use--two qualities that you don't see very often in the Java web application world.


If you want to execute some code when the application first starts up, you can create a class that has the @OnApplicationStart annotation and that extends the Job class. Put the code that you want to run on startup in a method called doJob(). This class can just go in the default package for simplicity, but it doesn't matter what package the class is in.

@OnApplicationStart
public class Bootstrap extends Job {
  @Override
  public void doJob(){
    if (User.count() == 0){
      Fixtures.loadModels("initial-data.yml");
    }
  }
}

In DEV mode, this will be run when the application gets its first request. That way, if an error occurrs, it will appear in the browser. But in PROD mode, the startup code will be run as soon as the play run command is executed and if there are any errors, the server will fail to start up.

To pass variables to a template, simply pass them as arguments to the render() method in the controller. The variable will have the same name inside the template as it does inside the controller.

If you want to run some code every time a controller handles a request, use the @Before annotation. For example, the addDefaults() method below will add two variables to the template every time a request comes in to the Application controller (the Play.configuration variable allows you to access values from the 'application.conf" file):


public class Application extends Controller {
  @Before
  public static void addDefaults(){
    //called before every request is handled
    renderArgs.put(
      "blogTitle",
      Play.configuration.getProperty("blog.title")
    );
    renderArgs.put(
      "blogBaseline",
      Play.configuration.getProperty("blog.baseline")
    );
  }

  //...
}

Play adds some helpful utility methods to various datatypes inside template code. Calling pluralize() on a number will return the string "s" if the number is not 1. Calling format('MM/dd/yyyy') on a Date object will format the date according to the given format string (you don't need to create a SimpleDateFormat object). Calling nl2br() on a string will replace all newlines with <br/> tags.

Tags are snippets of template code that you can insert into other templates by calling them like functions. The tag parameter names all begin with underscores in the tag file. Tag files go in the "views/tags" directory. The tag's name is the same as its file name (minus the file extension).

Calling a tag from a template:

#{hello person:'George', timeOfDay:'morning' /}

Tag file (views/tags/hello.html):

Good ${_timeOfDay}, <b>${_person}</b>!

Monday, September 5, 2011

The Play Framework - Part 2 - Database

The Play Framework is a MVC web application framework for Java that focuses on being light-weight and easy to use--two qualities that you don't see very often in the Java web application world.


To connect your application to a database, modify the "db.*" settings in the "conf/application.conf" file. To get up and running quickly, uncomment the "db=mem" line to create an in-memory database (all changes will be lost, of course, when the application ends).

To save data to the database, start by creating entity classes inside the "model" package. An entity class is a plain Java bean class that has JPA (Java Persistence Architecture) annotations. Each entity class represents a table in the database, each instance of the class represents a row in the table, and each field in the instance represents a column in the row (getter and setter methods aren't needed for the fields--Play generates them automatically). By default, the table name is the same as the class name. To change the table name, use the @Table annotation.

Each entity class can also optionally extend Play's Model class, which gives it access to utility methods for saving and retrieving data. For example, to insert a new row into the table, simply create a new instance of the class and call the save() method:

User user = new User("Bob", "bob@gmail.com");
user.save();

To retrieve data, call the static find() method:

List<User> users = User.find("byNameAndEmail", "Bob", "bob@gmail.com").fetch();

You don't need to write any SQL code to interact with the database. Play uses Hibernate for its persistence layer, so HQL (Hibernate Query Language) can be used for more complex queries.

The Model class also automatically generates an "id" primary key column for you (something that every table should have). So basically, you should always extend this class.

Here's an example of an entity class. It represents a blog post:

package models;
import java.util.*;
import javax.persistence.*;
import play.db.jpa.*;

@Entity
@Table(name="blog_posts")
public class Post extends Model {
  public String title;
  public Date postedAt;

  @Lob
  //large amount of text
  public String content;

  @ManyToOne
  //many Posts can belong to one User
  public User author;

  //a list of all comments that belong to this post
  //(the comments are in a separate table)
  //CascadeType.ALL = the post's comments will be automatically deleted when the post is deleted
  @OneToMany(mappedBy="post", cascade=CascadeType.ALL)
  public List<Comment> comments;

  public Post(User author, String title, String content) {
    comments = new ArrayList<Comment>();
    this.author = author;
    this.title = title;
    this.content = content;
    postedAt = new Date();
  }

  public Post addComment(String author, String content){
    Comment newComment = new Comment(this, author, content).save();
    comments.add(newComment);
    save();
    return this;
  }
}

The Fixtures class provides more utility methods for interacting with the database. For example, to delete the entire database, call the deleteDatabase() method. It can also execute SQL code contained in a file or persist the data in a specially-formatted YAML file (YAML is a new standard for representing structured data. Its aim is to provide a better alternative to XML).

Sunday, September 4, 2011

The Play Framework

The Play Framework is a MVC web application framework for Java that focuses on being light-weight and easy to use--two qualities that you don't see very often in the Java web application world. Writing a web application in Java has always been more complicated than, say, writing a web application in PHP.

The first thing you must do after downloading the Play framework is configure your path so that you can invoke the "play" executable:

PATH=$PATH:/home/user/play-1.2.2

Everything you do with Play is done through this play executable.

To create a new application, run this command:

play new appName

This creates a folder in the current directory with the same name as the application. The folder is populated with the basic scaffolding needed for a Play application.

You can immediately run this application too. To run the application, execute this command:

play run appName

This will start up a web server and run your application at "http://localhost:9000". You don't need any web servers of your own, everything is bundled within the framework (you don't even need a JavaEE web container like Tomcat). The only thing you need to run Play is a JRE.

Note that, if you get an error that says, "ERROR ~ Could not bind on port 9000", then something on your computer must be using port 9000. Port 9000 is the default port Play uses to run the application. This setting is defined in "conf/application.conf" under the "http.port" setting (be sure to uncomment the line too--remove the "#" at the beginning of the line to uncomment it). I changed the port to 9001 because 9000 didn't work for me.

Notice the line that says, "Listening for transport dt_socket at address: 8000", when the application is starting up. This means the web application has opened a port which allows you to debug the application as it is running using an IDE like Eclipse.

After it successfully starts up, open a web browser and navigate to "http://localhost:9001". When the web application gets its first request, it compiles all the Java code and template code in the application for you (it saves the .class files to the "tmp" directory). You don't have to manually compile any of the .java files yourself like in a normal JavaEE web application. If you change any Java code or template code while the application is running, the application will detect this and automatically recompile it for you. You don't have to restart the application. This is how the web application behaves in DEV (development) mode (the default). If started in PROD (production) mode, then this is not done in order to increase performance.

The application's unit tests (in the "test" folder) can be run from the web application itself. To do this, execute this command:

play test appName

This will start the web application and also enable the unit test functionality at "http://localhost:9001/@tests". The page displays all available tests and lets you select which tests to run.

Eclipse Integration

You can edit all of the files in a basic text editor of course, but for serious development work, this can be tedious. To configure the Play application for Eclipse, execute this command:

play eclipsify appName

This will create all the necessary configuration files (such as the ".project" file) needed to open the application as an Eclipse project. It also creates a directory named "eclipse", which contains launch configurations that can be run from Eclipse:

  • appName.launch - Running this has the same effect as running play run appName from the command line (it starts up the web application). To run it, right-click on it and select "Run As > appName".
  • Connect JPDA to appName.launch - This will connect Eclipse to the JPDA port (8000) while the application is running and allow you to debug the application in Eclipse. Note that the application must already be running for this to work. To run it, right-click on it and select "Debug As > Connect JPDA to appName". Go to the "Debug" perspective in Eclipse to see if it connected properly (you can see all the different web server threads in the upper-left hand corner).
  • Test appName.launch - Running this has the same effect as running play test appName from the command line. To run it, right-click on it and select "Run As > Test appName". Make sure that you first shut down the web application if you had already started it using "appName.launch".

Import the project into Eclipse by going to "File > Import..." and then selecting "Existing Projects into Workspace".

If you try to open some of the template files (the .html files in "app/views") in Eclipse, some files will display an error that says, "Character encoding "${_response_encoding}" is not supported by this platform." This is because Eclipse considers the file to be an HTML file and it looks at the <meta> tag to determine the character encoding of the file (even though the file has a ".html" extension and has HTML tags, it isn't really an HTML file--Play uses a special templating engine that has a special syntax). Well, the character encoding here is defined as a template variable, so Eclipse sees the variable name and gets confused. Click the "Set Encoding..." button and set the encoding to "UTF-8".

Tuesday, June 14, 2011

PHP - Relative paths and Phar Archives

Working with file paths and Phar archives in PHP can be tricky. The PHP code inside of a Phar file will treat relative paths as being relative to the Phar archive, *not* relative to the current working directory. Here's a short example:

Say you have the following files:
phar/index.php
test.php
my.phar
The index.php file is located inside of the phar directory. It is the bootstrap file for the phar archive:
function does_it_exist($file){
  return file_exists($file) ? "true" : "false";
}
The bootstrap file is executed when the phar file is included from a PHP script. Our bootstrap file will simply cause the function "does_it_exist" to be declared.

The file my.phar is the packaged phar archive (see the phar-util project for an excellent phar-building tool). It contains the index.php file at its root.

Let's try running different code inside of test.php and see what the results are for each run:
//Run 1:
require_once 'phar/index.php';  //PHP file
$file = __DIR__ . "/index.php"; //absolute path
echo does_it_exist($file);      //prints "false"

//Run 2:
require_once 'phar/index.php';  //PHP file
$file = "index.php";            //relative path
echo does_it_exist($file);      //prints "false"

//Run 3:
require_once 'my.phar';         //phar file
$file = __DIR__ . "/index.php"; //absolute path
echo does_it_exist($file);      //prints "false"

//Run 4:
require_once 'my.phar';         //phar file
$file = "index.php";            //relative path
echo does_it_exist($file);      //prints "true"
Look at Run 4. This code includes the phar file and passes the function a relative path. Relative to the current working directory, index.php does not exist. But relative to the contents of the phar archive, it does exist, which is why it prints "true"!

Any file paths that you manipulate inside of a phar archive must be absolute. If they are relative, the phar will treat the path as being relative to the phar archive, not relative to the current working directory, which may not be what you intended!

Sunday, May 8, 2011

WSDL SOAP bindings confusion - RPC vs document

What is the difference between RPC and document styles in SOAP web services?

I was asked this question at a job interview and was embarrassed to discover that I didn't know the answer (considering that I listed "SOAP web services" on my resume). I've heard the terms before, but couldn't remember what they meant. The main difference lies in what the body of the SOAP message looks like.

RPC vs document styles

The body of an RPC (remote procedure call) style SOAP message is constructed in a specific way, which is defined in the SOAP standard. It is built around the assumption that you want to call the web service just like you would call a normal function or method that is part of your application code. The message body contains an XML element for each "parameter" of the method. These parameter elements are wrapped in an XML element which contains the name of the method that is being called. The response returns a single value (encoded in XML), just like a programmatic method. The WSDL code for a RPC-style web service is less complex than that of a document-style web service, but this isn't a big deal since WSDLs aren't meant to be handled by humans.

A RPC-style request:
<soap:envelope>
  <soap:body>
    <multiply>    <!-- web method name -->
      <a>2.0</a>  <!-- first parameter -->
      <b>7</b>    <!-- second parameter -->
    </multiply>
  </soap:body>
</soap:envelope>

A document style web service, on the other hand, contains no restrictions for how the SOAP body must be constructed. It allows you to include whatever XML data you want and also to include a schema for this XML. This means that the client's and server's application code must do the marshalling and unmarshalling work. This contrasts with RPC in which the marshalling/unmarshalling process is part of the standard, so presumably should be handled by whatever SOAP library you are using. The WSDL code for a document-style web service is much more complex than that of a RPC-style web service, but this isn't a big deal since WSDLs aren't meant to be handled by humans.

A document-style request:
<soap:envelope>
  <soap:body>
    <!-- arbitrary XML -->
    <movies xmlns="http://www.myfavoritemovies.com">
      <movie>
        <title>2001: A Space Odyssey</title>
        <released>1968</released>
      </movie>
      <movie>
        <title>Donnie Darko</title>
        <released>2001</released>
      </movie>
    </movies>
  </soap:body>
</soap:envelope>

The main downside of the RPC style is that it is tightly coupled to the application code (that is, if you decide you want to call these web methods like normal methods--this is not a requirement, but this is what the RPC style was designed for). This means that if you want to change the order of the parmeters or change the types of those parameters, this change will affect the definition of the web service itself (just as it would affect the definition of a normal function or method).

Document style services do not have this issue because they are loosely coupled with the application code--the application must handle the marshalling and unmarshalling of the XML data separately. For example, with a document style service, it doesn't matter if the programmer decides to use a "float" instead of an "int" to represent a particular parameter because it's all converted to XML text in the end.

The main downside of the document style is that there is no standard way of determining which method of the web service the request is for. It's easy to get around this limitation, but, however it's done, it must be done manually by the application code. (Note: The "document/literal wrapped" style removes this limitation; read on for more details.)

Another point to note about the document style is that there are no rules for how the SOAP body must be formatted. This can either be seen as a downside or a strength, depending on your perspective. It's a strength if you are looking for the freedom to handle the message the way you want, but a downside if you don't want to have to do the extra marshalling/unmarshalling work that it requires.

Encoded vs literal encodings

In addition to the RPC and document styles, there are two types of encodings: "encoded" and "literal".

Literal means that the SOAP body follows an XML schema, which is included in the web service's WSDL document. As long as the client has access to the WSDL, it knows exactly how each message is formatted.

Encoded, on the other hand, means that the SOAP body does not follow a schema, but still follows a specific format which the client is expected to already know. It is not endorsed by the WS-I standard because there can be slight differences in the way in which various programming languages and web service frameworks interpret these formatting rules, leading to incompatabilities.

This makes for 4 different style/encoding combinations:

RPC/encoded - RPC-style message that formats its body according to the rules defined in the SOAP standard (which are not always exact and can lead to incompatabilities).
RPC/literal - RPC-style message that formats its body according to a schema that reflects the rules defined in the SOAP standard. This schema is included in the WSDL.
document/encoded - Document-style message that does not include a schema (nobody uses this in practice).
document/literal - Document-style message that formats its body according to a schema. This schema is included in the WSDL.

There's also a 5th type. It isn't an official standard but it is used a lot in practice. It came into being to compensate for document/literal's main shortcoming of not having a standard way of specifying the web method name:

document/literal wrapped - The same as document/literal, but wraps the contents of the body in an element with the same name as the web service method (just like RPC-style messages). This is what web services implemented in Java use by default.

Is my understanding of all this accurate? Which approach do you think is the best? Let me know in the comments.

References:


Sunday, April 24, 2011

Dropbox Tech Blog

The folks over at Dropbox recently started a new blog, which is focused on the technology that the Dropbox application uses. Their first blog post describes how the Dropbox team translated Dropbox into multiple languages.

It starts by acknowledging the success that Facebook had using community translation to translate their site to French in 2008. Dropbox, however, chose not to use this technique because of the significant effort required to build a framework that not only accepts community translations, but quality-checks them and converts them to the multitude of i18n file formats that Dropbox uses.

Instead, they decided to go with a hybrid approach--professional translators would do the bulk of the translation, while users would have the ability to make corrections. The idea being that since users are the ones using the application, they have a much better idea of the context in which a particular word or phrase is being used. Professional translators on the other hand, have likely never even heard of Dropbox, so may produce translations which don't quite capture the true meaning of a word or phrase.

Saturday, April 2, 2011

PHP-SQLUtils released

Yesterday, I created a project on github called PHP-SQLUtils. This is a small PHP library that helps make building SQL queries easier and less error-prone. I've been using a variant of this library at work and it has definitely come in handy. One thing that it can do is build INSERT statements.

In your typical INSERT statement, the list of column names come first, followed by the list of column values.
INSERT INTO cars
(make, model, year, purchased) VALUES
('Ford', 'Focus', 2005, '20050520 00:00:00')
It's a little hard to tell what values go with what columns. It gets harder as the list of columns gets longer.
INSERT INTO cars
(make, model, year, purchased, owner, seats, mpg_city, mpg_highway, color, sun_roof) VALUES
('Ford', 'Focus', 2005, '20050520 00:00:00', 'George Washington', 5, 30.4, 35.1, 'gray', 0)
PHP-SQLUtils provides an interface for building INSERT statements. It puts the column names right next to their values, making it easy to figure out what values belong to what columns and reducing the chance of a bug appearing:
$utils = new MssqlUtils();
$insert = $utils->insert("cars");
$insert->s("make", "Ford");
$insert->s("model", "Focus");
$insert->n("year", 2005);
$insert->d("purchased", strtotime("2005-05-20"));
echo $insert->done();
//prints "INSERT INTO cars (make, model, year, purchased)
//VALUES ('Ford', 'Focus', 2005, '20050520 00:00:00')"
Check out PHP-SQLUtils here.