Friday, December 28, 2012

Using custom models in routes in Play framework Java 2.x, aka PathBindable.

If you want to reduce clutter in your controllers you can use PathBindables to automatically convert URL parameters to your model objects or other custom objects. For example you can get rid of the code that takes an id, looks up the user in a database and checks for null etc by wrapping into a custom PathBindable implementation. This will also make it easier to reuse code among your controllers.

You will need to do 3 things to get this to work,

1. Create a controller and action, such as
public static userName(User user)
{
   return ok(user.getName());
}

Note that user is always non null and is safe to use. An exception is thrown internally if the lookup fails and Play will return a bad request response to the client.

2. Create a route, such as
GET /user/:user   MyController.userName(user : models.User)

Here we create an actual callable URL, for example, /user/124. In this example we use the id in the route but it can be anything that you can map to your model, for example unique email addresses.

3. Implement the PathBindable interface

You can add the PathBindable code to your existing model,

package models;

import javax.persistence.Entity;
import javax.persistence.Id;

import play.Logger;
import play.db.ebean.Model;
import play.db.ebean.Model.Finder;
import play.mvc.PathBindable;

@Entity
public class User extends Model implements PathBindable
{
    @Id
    Long id;

    String name;

    public String getName()
    {
        return name;
    }

    @Override
    public User bind(String key, String id)
    {
        // key is "user"
        // id is the ":user" part of the route, i.e. 1 if you have /user/1
        User user = find.byId(new Long(id));
        if (user == null)
            throw new IllegalArgumentException("User not found");
        return user;
    }

    @Override
    public String javascriptUnbind()
    {
        return null;
    }

    @Override
    public String unbind(String arg0)
    {
        return name;
    }

    public static Finder find = new Finder(Long.class, User.class);
}
References, https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/java/play/mvc/PathBindable.java http://julien.richard-foy.fr/blog/2012/04/09/how-to-implement-a-custom-pathbindable-with-play-2/

Friday, November 16, 2012

Dojo strikes back

Dojo is nice and you can do nice things quickly with it once you have learned all of it's oddities and strange behaviour. Today I ran into this really crappy thing, dijit.form.Checkbox.getValue() returns either "on" if it is checked or false if it isn't! WTF

// rant over...

Sunday, November 11, 2012

SSH Deployment module for Play 1.2.x released!

This modules simplifies deployment of Play 1.2.x application instances to Linux servers. Changes are pushed to servers using rsync and can be started, stopped and restarted over SSH. Combining this plugin with SSH keys you get a really easy way of deploying your code to testing instances and to production. It also works well in continuous integration setups.

Here is some of the copy pasted docs I wrote (for full docs, go here),


What it does

Easily deploy your application to Linux boxes using SSH and Rsync. You can deploy the same application to multiple machines, for example pushing to a test environment or multiple production backend nodes.

Usage

Push changes to server

    play deploy:update

Start, stop & restart your play application

    play deploy:start
    play deploy:stop
    play deploy:restart

The module supports command line arguments for overriding any of the parameters, you can also specify which instance to use (deploy.INSTANCE_NAME.host=10.0.0.1 etc). For full docs see, https://github.com/nylund/play-deploy/blob/master/documentation/manual/home.textile


Setup

Add this to your application.conf:

    deploy.default.host=IP_or_hostname
    deploy.default.login=remote_user_name
    deploy.default.port=remote_port
    deploy.default.path=remote_directory, for example /home/user/app-deploy/test1
    deploy.default.play_path=remote_path_to_play_binary, for example /home/user/app-deploy/play-1.2.5/play

Add this to your dependencies.yml:

     require:
        - play
        - deploy -> deploy 0.1
     repositories:
        - deploy:
            type: http
            artifact: http://albin.abo.fi/~ninylund/play_modules/deploy-0.1.zip
            contains:
                - deploy -> *



Get the module, http://www.playmodules.net/module/34
Check the code at Github, https://github.com/nylund/play-deploy