Selenium WebDriver and Play

big-logo
I have advocated tests using Selenium WebDriver in the past many times. Will it become a de facto standard now that frameworks like Play make it very easy ?

It is not even evident below that Selenium WebDriver is being used. It is HTMLUNIT that is imported statically.

A test server is started, a test application is setup and a browser is simulated, all in a few lines of code. Very economical.


import static org.fest.assertions.Assertions.assertThat;
import static play.test.Helpers.*;

import org.junit.Test;

import controllers.routes;
import play.Logger;
import play.libs.F.Callback;
import play.test.TestBrowser;
import static helpers.TestSetup.*;

public class ProposalSubmissionTest {

	@Test
	public void proposalTest(){
		running(testServer(3333,fakeApplication(testDbSettings())),HTMLUNIT, new Callback<TestBrowser>(){

			@Override
			public void invoke(TestBrowser browser) throws Throwable {
				browser.goTo("http://localhost:3333" + routes.MainController.newProposal().url());
				assertThat(browser.title()).isEqualTo("New Proposal");
				Logger.debug(browser.title());
			}
			
		});
	}
}

Reactive application

I really cannot believe that the firms in Chennai do not have any need for newer technology. On the one hand requirements are clear about scalability, resilience etc. On the other hand the developers do not show interest in new ideas. We had a requirement to notify users when reports are generated in the background thread.

Why don’t we read books and learn to use newer ideas ?

Play has an event handling mechanism that publishes events that refresh the browser with new data.

When I submit new data in the browser on the right, it shows up immediately in the other browser.

Events

Play User Interface Lesson

I have just completed the UI using Play’s assets. I need to explore the asset controller and compiler. This seems to be interesting and is not part of any Java framework I have used.

 

Image

 

 

I had to install Sass

Play deployment to CloudBees

I followed the instructions to deploy the Play application to CloudBees.

CloudBees SDK

I installed this SDK to interact with the cloud infrastructure. So this created a profile based
on my CloudBees account.

Mohans-MacBook-Pro:cloudbees-sdk-1.5.2 radhakrishnan$ bees help
# CloudBees SDK version: 1.5.2
# CloudBees Driver version: 1.3.8
Installing plugin: org.cloudbees.sdk.plugins:ant-plugin:1.3.0

You have not created a CloudBees configuration profile, let’s create one now…
Enter your default CloudBees API end point [us | eu]: us
Enter your CloudBees account email address: radhakrishnan.mohan@gmail.com
Enter your CloudBees account password:
Plugin installed: org.cloudbees.sdk.plugins:ant-plugin:1.3.0
Installing plugin: org.cloudbees.sdk.plugins:app-plugin:1.5.6
Plugin installed: org.cloudbees.sdk.plugins:app-plugin:1.5.6
Installing plugin: org.cloudbees.sdk.plugins:config-plugin:1.3.2
Plugin installed: org.cloudbees.sdk.plugins:config-plugin:1.3.2
Installing plugin: org.cloudbees.sdk.plugins:db-plugin:1.3.3
Plugin installed: org.cloudbees.sdk.plugins:db-plugin:1.3.3
Installing plugin: com.cloudbees.sdk.plugins:service-plugin:1.2.3
Plugin installed: com.cloudbees.sdk.plugins:service-plugin:1.2.3
Type ‘bees help ‘ for help on a specific subcommand.

SDK subcommands:
help List all commands
init Re-initialize the SDK config file
plugin:delete Delete a SDK plugin
plugin:info Get SDK plugin information

Application deployed to CloudBees

app

Provisioned MySQL on CloudBees

db

The parameters I was supposed to set

Mohans-MacBook-Pro:cloudbees-sdk-1.5.2 radhakrishnan$ bees config:set -a mohanr/playconf AppDynamics=false
Application config parameters for mohanr/playconf: saved

Application Parameters:
applyEvolutions.default=true
DB_USER=mohanr
DB_PASS=test
DB_URL=jdbc:mysql://ec2-50-19-213-178.compute-1.amazonaws.com:3306/playconftest
applyDownEvolutions.default=true
AppDynamics=false
Runtime Parameters:
java_version=1.7

The settings to enable evolutions did not work and I could not access the application.

So I switched off the evolution facility and removed 1.sql and then deployed the application. I think this evolution facility can be switched off in application.conf also.

Application Parameters:
DB_USER=mohanr
DB_PASS=test
applyDownEvolutions.default=false
applyEvolutions.default=false
DB_URL=jdbc:mysql://ec2-23-21-211-172.compute-1.amazonaws.com:3306/helloplaytest
AppDynamics=false
Runtime Parameters:
java_version=1.7

Deployment

Mohans-MacBook-Pro:hello-play radhakrishnan$ ./activator dist
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading project definition from /Users/radhakrishnan/Documents/hello-play/project
[warn] Multiple resolvers having different access mechanism configured with same name ‘typesafe-ivy-releases’. To avoid conflict, Remove duplicate project resolvers (`resolvers`) or rename publishing resolver (`publishTo`).
[info] Set current project to hello-play (in build file:/Users/radhakrishnan/Documents/hello-play/)
[info] Packaging /Users/radhakrishnan/Documents/hello-play/target/scala-2.10/hello-play_2.10-1.0-SNAPSHOT-sources.jar …
[info] Done packaging.
[info] Main Scala API documentation to /Users/radhakrishnan/Documents/hello-play/target/scala-2.10/api…
[info] Wrote /Users/radhakrishnan/Documents/hello-play/target/scala-2.10/hello-play_2.10-1.0-SNAPSHOT.pom
[info] Packaging /Users/radhakrishnan/Documents/hello-play/target/scala-2.10/hello-play_2.10-1.0-SNAPSHOT.jar …
[info] Done packaging.
model contains 30 documentable templates
[info] Main Scala API documentation successful.
[info] Packaging /Users/radhakrishnan/Documents/hello-play/target/scala-2.10/hello-play_2.10-1.0-SNAPSHOT-javadoc.jar …
[info] Done packaging.
[info]
[info] Your package is ready in /Users/radhakrishnan/Documents/hello-play/target/universal/hello-play-1.0-SNAPSHOT.zip
[info]
[success] Total time: 16 s, completed Feb 23, 2014 9:23:11 PM
Mohans-MacBook-Pro:hello-play radhakrishnan$ bees app:deploy -a playconf -t play2 target/universal/hello-play-1.0-SNAPSHOT.zip
-bash: bees: command not found
Mohans-MacBook-Pro:hello-play radhakrishnan$ source ~/.profile
Mohans-MacBook-Pro:hello-play radhakrishnan$ bees app:deploy -a playconf -t play2 target/universal/hello-play-1.0-SNAPSHOT.zip
Deploying application mohanr/playconf (environment: ): target/universal/hello-play-1.0-SNAPSHOT.zip
Application parameters: {containerType=play2}
……………………uploaded 25%
……………………uploaded 50%
……………………uploaded 75%
……………………upload completed
deploying application to server(s)…
Application mohanr/playconf deployed: http://playconf.mohanr.cloudbees.net

Create tables using MySQL Workbench

MySQL Workbench

The application was accessible now as the following screenshots show.

New Proposal

Submitted Proposal

Play framework form validation errors

I post as I work my way through the Play material. I have not still read The reactive manifesto and relate it to Play. So I used the same classic trick popularized by Struts to debug this. As far as this type of error display mechanism is concerned I did not find anything different between Play and old versions of Struts.

Problem

I did not initialize isApproved to false.

package models;

import javax.persistence.*;
import javax.validation.Valid;

import play.data.validation.Constraints.MaxLength;
import play.data.validation.Constraints.MinLength;
import play.data.validation.Constraints.Required;
import play.db.ebean.*;

@Entity public class Proposal extends Model {

	@Id
	public String id;
	
	@Required public String title;
	
	@MinLength(value = 10)
	@MaxLength(value = 1000)
	@Column(length=1000)
	public String proposal;
	
	@Required public SessionType type = SessionType.OneHourTalk;
	
	@Required public Boolean isApproved;
	
	public String keywords;
	
	@Valid
	@OneToOne(cascade=CascadeType.ALL)
	public Speaker speaker;
}

Display errors

@(proposal: play.data.Form[Proposal])

@import helper._


@main("New Proposal"){

	@if(proposal.hasErrors) {
        <div class="alert alert-error">
            @proposal.errors
        </div>
	}

	@form(action = routes.MainController.submitProposal()){
	<h3>Proposal</h3>
    @inputText(proposal("title"))
    @textarea(proposal("proposal"))
    @inputText(proposal("keywords"))
	<h3>Speaker</h3>
    @inputText(proposal("speaker.name"))
    @inputText(proposal("speaker.email"))
    @textarea(proposal("speaker.bio"))
    @inputText(proposal("speaker.twitterId"))
    @inputText(proposal("speaker.pictureUrl"))
    
	<p class="submit">
				<button type="submit" class="button green" id="submitForm">Submit</button>
	</p>
    }
}

Error message

I can customize it but this sufficed.

Screen Shot 2014-02-23 at 5.14.17 PM

Default settings for Play Java applications

I started worked with a play example and encountered this error.


package controllers;

 

import models.Proposal;

 

import play.data.Form;

import play.mvc.Controller;

import play.mvc.Result;

import play.mvc.Results;

import models.*;

 

public class MainController extends Controller {

  

    public static Result welcome(String name) {

        return ok("<h1> Welcome " + name + "</h1>").as("text/html");

    }

 

    public static Result index() {

        return ok(views.html.index.render("Hi from Java"));

    }

    

    public static Result newProposal(){

    Form<Proposal> proposalForm = Form.form(Proposal.class);

    

    return ok(views.html.newProposal.render(proposalForm));

    }

    

    public static Result submitProposal(){

    return Results.TODO;

    }

    

}

Error

[error] /Users/radhakrishnan/Documents/hello-play/app/controllers/MainController.java:23: error: incompatible types: play.data.Form cannot be converted to play.api.data.Form
[error] return ok(views.html.newProposal.render(proposalForm));

I struggled with this error until I set play.Project.playJavaSettings in my build.sbt

Play Framework

I was trying to use the activator UI to play with the Play Framework. It worked except for this annoying issue.

So I switched to the eclipse setup which works quite well.

[hello-play] $ Mohans-MacBook-Pro:hello-play radhakrishnan$ ./activator
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading project definition from /Users/radhakrishnan/Documents/hello-play/project
[warn] Multiple resolvers having different access mechanism configured with same name ‘typesafe-ivy-releases’. To avoid conflict, Remove duplicate project resolvers (`resolvers`) or rename publishing resolver (`publishTo`).
[info] Set current project to hello-play (in build file:/Users/radhakrishnan/Documents/hello-play/)

Generate an eclipse project

[hello-play] $ eclipse with-source=true
[info] About to create Eclipse project files for your project(s).
[info] Resolving com.typesafe.atmos#atmos-sigar-libs;1.3.1 …
[info] downloading http://repo1.maven.org/maven2/org/scala-lang/scala-library/2.10.2/scala-library-2.10.2-sources.jar
[info] [SUCCESSFUL ] org.scala-lang#scala-library;2.10.2!scala-library.jar(src) (41827ms)

Change and save

Screen Shot 2014-02-16 at 8.57.20 PM

Hot deploy

[hello-play] $ ~run

— (Running the application from SBT, auto-reloading is enabled) —

[info] play – Listening for HTTP on /0.0.0.0:9000

(Server started, use Ctrl+D to stop and go back to the console…)

[success] Compiled in 715ms
[info] play – Application started (Dev)
[info] Compiling 1 Java source to /Users/radhakrishnan/Documents/hello-play/target/scala-2.10/classes…
[success] Compiled in 4s

— (RELOAD) —

[info] play – Application started (Dev)

Change in view

Screen Shot 2014-02-16 at 8.53.10 PM