More Than One FieldConstructor with Play Framework

Often times in the Play Framework, I need to have more than one custom field constructor. Figuring out how to do this the first time took a lot of work to get it right. Here I discuss how you can create and use more than one custom field constructor in your next Play Framework 2.3.X application.

Background

The Play Framework has a set of helpers that makes building forms quick and easy. These helpers take care of populating your form elements with the correct values based upon some object that you have kicking around. For example, assuming that you have a simple User class that keeps track of user information:

public class User {
    @Constraints.Required
    public String name;
    @Constraints.Required
    public String twitterId;
}

Here there are two attributes we are keeping track of: a user’s name and twitterId. To build a form in the controller, we convert that class into a Form object
and pass it to our HTML template. So the controller for example, may have a method that looks something like this:

public static Result userDetailsForm() {
    Form userForm = Form.form(User.class);
    userForm = userForm.bindFromRequest(request().body().asFormUrlEncoded());
    return ok(views.html.userdetails.render(userForm));
}

This controller does the work of transforming our simple User class into a form object. In this example, we take any data that was passed to the controller in a POST statement, and bind it to the form. We pass that form object to an HTML template called userdetails.scala.html. In the HTML template is some code that actually lets us construct a form quite easily using the Play Framework helpers:

@(userForm: Form[User])
@import views.html.helper._

Simple User Form

@helper.form(action = routes.Application.saveUserDetails()) {
    @inputText(userForm("name"))
    @inputText(userForm("twitterId"))
}

The Problem

When creating a form with the Play Framework, you want your input elements to match the style of the rest of your page. Usually, it’s just a matter of applying the class that you want directly to your input elements. For example, if you are familiar with Bootstrap, you usually want to apply a class such as form-control to your input element. This is accomplished by inserting the element into the open set of parameters when you use the field that you want. You probably also want to use a better descriptor for the field; the label element will let you do that. You may also want to use some placeholder value to show the user an example of what they can type:

@inputText(userForm("name"),
    '_label->"User Name",
    'placeholder->"e.g. John Smith",
    'class->"form-control")
@inputText(userForm("twitterId"),
    '_label->"Twitter ID",
    'placeholder->"e.g. myTwitterID",
    'class->"form-control")

This will append the class information to the form element that you want to create. This is good, since it allows easy customization without having to write the HTML yourself. It also lets Play Framework handle the nitty gritty details of putting values into those input elements so that you don’t have to. This is a life saver when you have select elements that have lots of potential values. The rendered input elements would look something like this:

simple-user-form

Note that to generate the above input, I actually have a template system already in place that is including the correct Bootstrap CSS and Javascript.

This is good, but what happens if you want to create an input group and put an @ sign in front of the Twitter ID like so:

simple-user-form-with-at

To accomplish this, you need a custom field template to generate a FieldConstructor.

Anatomy of a Custom Field Template

Although they sound complicated, a custom field template is nothing more than an HTML template that accepts a helper.FieldElements parameter as input to the form. That’s really about it. Aside from that, they contain the HTML that you define to draw the form element. In the case of our @ sign appearing in front of the Twitter ID field, we need to create a span element before the input box that will render whatever text we pass in. I created an HTML template as a file called twitteridinput.scala.html with this template in it:

@(elements: helper.FieldElements)
<label for="@elements.id">@elements.label</label>
<div class="input-group @if(elements.hasErrors) {has-error}"><span class="input-group-addon">@elements.args.get('_prepend)</span> @elements.input</div>
<div class="info">@elements.infos</div>
@if(elements.hasErrors){
<div class="input-group has-error"><span class="help-block">@elements.errors</span></div>
}

As you can see in the code, the @elements parameter is what holds all of the field elements that get passed to the constructor. The attributes id, label, and infos all get populated from the form field that is passed it (more on that below). Aside from those, is an attribute called hasErrors that is true if there are errors with the field. The errors attribute has the actual error text. As you can see here, I check to see if there are fields with errors, and if so, I generate some friendly HTML to alert the user to the error. Finally, the input attribute contains the code to generate the actual input element that we want.

The real magic is in the “ class. How does it work? In addition to all the other attributes contained within the elements object is args. This contains a list of key -&gt; value pairs. You can put anything you want into that list. We saw this above with the '_label, 'placeholder and 'class parameters. In the case of this simple template, I expect a key called '_prepend which will have whatever you want to be pre-pended to the field. Whatever is in that named attribute will be displayed within the span class.

Using the Template

To use the new custom field template, we have to generate a FieldConstructor for it. This is a helper class in the Play Framework which will take care of a lot of the busywork for us (binding the correct things from the userForm field to the helper.FieldElements). To generate the FieldConstructor, all you need to do is put the following in the userdetails.scala.html template:

@twitterField = @{ FieldConstructor(twitteridinput.f) }

Then, to apply that template to the element that you want, you just need to specify it as the handler for that field. For example, to apply it to our Twitter ID field:

@inputText(userForm("twitterId"),
    '_label->"Twitter ID",
    '_prepend->"@",
    'placeholder->"e.g. myTwitterID",
    'class->"form-control"
)(handler = twitterField, implicitly[Lang])

That’s it! Note that the handler isn’t the only thing we have to specify – we must implicitly pass the language to the template helper too. All together, this is what is needed to generate the simple form:

@(userForm: Form[User])
@import views.html.helper._
@twitterField = @{ FieldConstructor(twitteridinput.f) }

Simple User Form

@helper.form(action = routes.Application.userDetailsForm()) {
    @inputText(userForm("name"),
        '_label->"User Name",
        'placeholder->"e.g. John Smith",
        'class->"form-control")
    @inputText(userForm("twitterId"),
        '_label->"Twitter ID",
        '_prepend->"@",
        'placeholder->"e.g. myTwitterID",
        'class->"form-control"
    )(handler = twitterField, implicitly[Lang])
}

Using this method, you can have several different custom field formats in your template. Simply define the templates you want to use, and apply them as handlers to whatever fields you need when generating your forms.

Writing a Play Framework Plugin in Java

I really like using the Play Framework to write simple web applications and REST interfaces. One of the interesting things about the Play Framework is that it is meant to be both stateless and asynchronous. The stateless nature of the framework makes it easy to scale very quickly, since all you need to do is deploy multiple instances of your web application in order to serve larger loads.

Sometimes however, you need to introduce some sort of mechanism to create a global variable or object. For example, if your application needs to make an expensive database connection, sometimes it is better to create a single object (or pool of objects) that can handle your database connection, and have your controllers pick those up instead of generating new ones each time a REST endpoint or webpage is served. In this post, I’ll look at creating a Play Framework plugin, and how you can maintain a global state with that plugin.

The Problem

There are times that I have an Android emulator running and I want to issue it external events programmatically. The trick here is that I want to do it from within the emulator. More specifically, when I’m running tests for an application that receives SMS messages, it’s nice to be able to trigger an inbound SMS on demand. You can trigger SMS messages by opening a telnet session to your emulator and issuing the sms command. For example, assuming your emulator is running on port 5554, a typical session might look like this:

# telnet localhost 5554
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Android Console: type 'help' for a list of commands
OK
sms send 5550100 This is a test message!!
OK

The running emulator instantly receives it:

sms-message-android

If I’m doing a lot of automated testing directly on the Android emulator, I want the emulated Android test cases to easily trigger an incoming SMS by itself. To get this functionality, I want to spin up a Play application on my testing machine that can open telnet sessions to the running emulators. The application would accept REST calls to generate the required incoming SMS, and post them to the correct virtual device.

Sidenote: how do the tests running on the Android emulator know what emulator they are running on? Easy – the last 4 digits of the emulated device’s phone number are the telnet port that it is running on. The test case can use TelephonyManager getLine1Number() to read the telephone number, and parse the port number. It then passes the port number on to the Play application when it makes the call to the REST API.

The Solution

To do this, I built a telnet manager class that would connect to the emulator, and then allow me to input commands and capture the output. To connect this telnet manager to my Play application, I needed to keep the telnet manager object around in some sort of global variable and make it accessible, since I didn’t want to connect and disconnect from the running emulator every single time I wanted to run a command.

There are two different approaches that would work for creating this type of global object. The first is to create an Actor that would work through Akka. I didn’t investigate how this was done, but instead opted to create a Play plugin. The benefit of creating a Play plugin is that they are very easy to create. The breakdown for creating the Play plugin is as follows:

  1. Create the class that you want to manage your service.
  2. Create a class that implements play.api.Plugin interface.
  3. Add the plugin to your Play configuration.

Creating the TelnetManager

There isn’t too much to say about this step of the solution. In my case, I have a simple TelnetManager class that I am using to connect to a running emulator. With my class, I can open up a connection to a running emulator, and then issue commands to it. The idea is that the Play framework application can open a connection to an emulator, and keep that connection open between different REST calls.

Since I know it’s bad if two different processes try and use the object at the same time, I used a simple lock variable to block until the resource becomes free. This ensures that two processes don’t try and talk to the same device at the same time.

Creating the Play Framework Plugin

All you need to do is implement the play.api.Plugin interface. Minimally, it looks like this:

package plugins;
 
import models.TelnetManager;
import play.Application;
import play.api.Plugin;
 
public class AndroidSMSMessagerPlugin implements Plugin {
 
    private final TelnetManager sTelnetManager = new TelnetManager();
 
    public AndroidSMSMessagerPlugin(Application app) {
    }
 
    public void onStart() {
        sTelnetManager.start();
    }
 
    public void onStop() {
        sTelnetManager.stop();
    }
 
    public boolean enabled() {
        return true;
    }
 
    public TelnetManager getTelnetManager() {
        return sTelnetManager;
    }
}

From the above code, you can see that there are only 4 methods that you need to implement in your Plugin:

  • onStart – runs any code that you need to run when the plugin is started by the Play framework. In my case, I have a start() function in my TelnetManager class that initializes a connection pool.
  • onStop – runs any code that you need to run when the plugin is stopped. In my case, I have a stop() function that destroys any open connections to any of the emulators, and releases any handles that it held open.
  • enabled – tells the Play framework if the plugin is actually enabled.
  • getTelnetManager – this is where the magic is. This function returns a handle to the globally opened TelnetManager object. With this function, I can use this in any of my controllers to actually get a reference to the global object (more on this below).

With those methods implemented, the last step is to configure your Play application to recognize the plugin.

Adding the Plugin to your Play Configuration

The easiest way to add your new plugin is to create a file in the conf of your project called play.plugins. In it, all you need is the following line:

2000:plugins.AndroidSMSMessagerPlugin

The 2000 acts as a priority level. The lower the number, the sooner the plugin is loaded (values can range from 0 – 10000). This can help you control when your plugin is loaded by the framework.

Accessing the Plugin

With everything plugged into the framework, the last thing to do is to actually access the plugin from a controller. You can do it with the following:

TelnetManager tm = Play.application().plugin(AndroidSMSMessagerPlugin.class).getTelnetManager();

As you can see, I now have a reference to the global TelnetManager object!

Wrapping Up

In this post, I went over how to create a Play framework plugin, and why you might need one. By implementing only 4 methods, you can easily create your own plugin to the Play framework.