Wednesday, September 18, 2013

Play2 @CloudBees

Play2 @CloudBees


CloudBees & Play2 Java?


CloudBees gives you kickstart, if you are a Scala fellow. They build you app with everything included, deploy it, and you just need to get it down to your own sandbox to develop it further. 

For Play2 Java they don't offer same option. Java can be taken in use without problems, anyway, since you just need to add needed dependencies for libraries you use and start coding.

http://www.playframework.com/documentation/2.2.x/Deploying-to-CloudBees

Recipe


Register free account 

Create Play2 app at Clickstart

Test your app

Find url to repository

Clone app

Make changes


Edit templates
  • any file goes, but on scala html templates you see changes right away
  • example, file: app/views/index.scala.html, change text: "What's your name"

Push changes
  • git add -A
  • git commit -m 'change'
  • git push origin master

Test your app again

Further steps


CloudBees goes on Play2 in full Scala mode - also: example app created by ClickStart doesn't have Java option. Fine for many, but I wanted still to work with Java, and so do many of us - old legacy java coders don't convert to Scala overnight, and neither do managers.

I felt CloudBees bit confusing. There's couple of deploying options for changes, couple of ways developing your initial seed app, and it was not cleat to me what is preferred way. I tried plugins and git deployments, and managed to push post my changes to git and deploy new version of app  to CloudBees, but I didn't feel it intuitive to control deployments.

Tuesday, September 17, 2013

Play2 @Heroku

Play2 @Heroku 

It's professional to keep your app running smoothly 

We all want to share some high time after being so many times left alone and down with self deployed brittle single server solutions. No matter if it was ok for customers to have unreliable and unscalable solution, it didn't ever felt good to me.

Play2 is excellent fit for shared computing resources as it's 100% asynchronous and stateless. Heroku is just one platform for your Play2 app, but as it's simple to use and has native support I recommend you to take a look.


Howto


Herokus Play2 support works seamlessly if your application is at root of your repository. To ensure this you may need move it there. More of it later.


Ingredients


  • Play2
  • Git
  • Heroku Toolbelt
You propably have Play2 and Git installed, so just go here to get Toolbelt https://toolbelt.heroku.com/


Baking


Go to your github account or create one

Create github repository 
  • heroku-play2
  • PlayFramework as gitignore
Clone repository to local disk 
Go to local repository
  • cd heroku-play2
Create new app
  • play new heroku-play2
    • accept name of app (enter)
    • Create a simple Java application (2)

Gotzha

  • Move newly created app to from ./heroku-play2 to .

Modify your app (optional)
  • go to /heroku-play2/app/views
  • edit index.scala.html
Login to your Heroku account
  • Heroku login
    • If you don't have heroku account now is time to create it
    • otherwise give your credentials
Deploy your app to Heroku
  • git push heroku master
Open your app from heroku
  • heroku open


Further steps


If you have ever deployed traditional however simple app to any java container, or to any shared deployment environment, you probably felt difference.

Sure: there's more to come, as you have development environments, QA, and need to continuously deliver to production, but you are not alone here either.

If you want to see where you might end up with real world complexity, read https://devcenter.heroku.com/articles/multiple-environments

Monday, September 16, 2013

Play2 charts

Play2 charts

Play2 data visualizations


Play2's nature of pure asynchronous web framework instead of all-you-ever-need "wundertute" makes it clear that developer is one who decides what and how to visualize - there's no built in default toolset present.

I decided to 
  • Use javascript library to visualize my data
  • Compare 2 datasets to each other using Radar Chart

Javascript libraries


There's plethora of different libs. Open source, free, you name it. One size doesn't fit all, and it's up to your needs what you're about to choose.

You want to go commercial way: Maybe Highchart? See what they offer: http://www.highcharts.com/demo/

You prefer open source, and can extend given implementation by yourself if needed: Maybe D3? Fancy, indeed! https://github.com/mbostock/d3/wiki/Gallery

Radar Chart

Radar Chart isn't exactly the most common chart, so Highchart & D3 didn't have it included - but wait... There's radar chart extensions to d3, and extensions extension http://nbremer.blogspot.nl/2013/09/making-d3-radar-chart-look-bit-better.html

I decided to go for simple basic implementation. It seemed to me complete adequate to present 2 datasets, one having reference data and one containing data from main entity shown at view. What user will see is single page which holds data of entity and radar chart showing selection of actual data and pre-defined boundaries.

Good old GoF MVC


Play2 is built around MVC-pattern. I decided to get data from store (yaml file) at controller, build there simple model of java structure from lists and maps and pass it to view. This is exactly what you do if your application is simple.
If your needs are more rigid you might want to get data at view thru separate Url. Url may point to Play2 based Json service or some external data source, in which case you'd probably need to develop some data transformations. 

Or do you want to build realtime websocket based live views? Play2 is your partner here. For very fancy asynchronous live views example see http://aredko.blogspot.de/2013/05/real-time-charts-with-play-framework.html

My Model


Model is Yaml file containing 2 datasets, which are read to 2 java classes, i.e. MetricSet which contains multiple Metric objects is populated. Dataset1 can be thought to be reference data, which shows boundaries to which data from dataset2 is to be compared. 

private static List<MetricSet> expected = null;
static {
try {
if (expected == null) {
Map<String, List<MetricSet>> all = (Map<String, List<MetricSet>>) Yaml
.load("default-metrics.yml");
expected = all.get("expectations");
Logger.info("Defaults added");

}
} catch (Exception e) {
Logger.error("Defaults couldn't be added " + e.getMessage(), e);
}
}

My Controller


On controller model which is pre-loaded to static member variable is converted to structures which correspond d3 radarcharts data structures. Getting from My Model to List<List<Map<String, Object>>> is trivial.

public static Result show(long evaluationId) {

..

List<List<Map<String, Object>>> radarMetrics = new ArrayList<List<Map<String, Object>>>();
for (MetricSet metricSet : expected) {
List<Map<String, Object>> ds = new ArrayList<Map<String, Object>>();
for (Metric metric : metricSet.metrics ) {
Map<String, Object> item = new HashMap<String, Object>();
item.put("axis", metric.name);
item.put("value", metric.value);
ds.add(item);
}
radarMetrics.add(ds);
}

return ok(views.html.evaluations.show.render(evaluation, radarMetrics));
}

View


View gets data structures thru metrics parameter, which is of type List[List[Map[String, Object]]] as expressed with Scala. Note that view contains import of Google Gson. View has javascript that transforms metrics parameter to Json with Gson, adds some configuration, and renders radar chart.

@(evaluation: models.jpa.Evaluation)(metrics:List[List[Map[String, Object]]])

@* JSON marshalling *@
@import com.google.gson.Gson

@main("Evaluation") {

<script type='text/javascript' src='@routes.WebJarAssets.at(WebJarAssets.locate("d3.js"))'></script>

<script type='text/javascript' src='http://graves.cl/radar-chart-d3/src/radar-chart.js'></script>
   
<div id="chart" style='float:left'></div>

<script type='text/javascript'>//<![CDATA[ 

// get data
var data = @{Html(new Gson().toJson(metrics))};

// build config
var cfg = {
  w: 500,
  h: 500,
  maxValue: 100,
  levels: 10,
}

// render
RadarChart.draw("#chart", data, cfg);    

//]]>  

</script>

Sources


Further steps


Current design creates radar chart targeted copy of model inside controller as part of transformation, which means data duplication, but also makes controller responsible of tasks which belong to view.

It's possible to modularize given example by providing view helper which knows how to create radar chart compatible data structures from model classes. Provided helper should encapsulate data structure transformations, which are currently on controller, and delegate transformation responsibility to view instead of controller. 

There's manyfold of gains keeping it clear that views are in charge of presentation. When model classes can be transformed to Json data structures using single component inside view you can reuse logic easily in case you need radar chart in multiple pages, but also reacting on changes of javascript library or replacing used library with some other gets lot easier. 

Tuesday, September 03, 2013

Play2 javascript library dependencies

Play2 javascript library dependencies

Dependency management problem

It's common practice in java domain to rely on dependency management infrastructures like Apache Maven. As one starts to develop html app's with various javascript libraries it's necessary to manually copy files and adjust paths, which is error prone. In maven you would do this by changing single line, but now instead of changing version number on one file quite a lot simple manual operations are needed.

Asset management on Play2

Javascript libraries are used on html pages, which means they are carried to client over http as requested by browser. On server side resides mapping from http Url to location of requested resource on servers disk.

Play2 serves static assets from Public directory using Assets controller. This mechanism is defined at conf/routes file.


# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file               controllers.Assets.at(path="/public", file)

Webjars is library which makes it possible to serve static content from jars which are acquired thru Apache IVY dependency management.

When your container, web framework, or application needs to serve static assets from Jar files webJar needs to be a dependency of your application.

Defining Play2 dependencies

Please select which webjars-play fits to Play2 version in use, then add to project/build.scala needed dependencies for webjars.

  val appDependencies = Seq(
    "org.webjars" %% "webjars-play" % "2.1.0-3",

and for components you use
  • "org.webjars" % "jquery" % "2.0.3",
  • "org.webjars" % "bootstrap" % "3.0.0",

Serving static content from jars

To serve static content from jars one needs to add route to files. Here's example you can use

conf/routes

# Map static resources from the jar packages to the /webjars URL path
GET     /webjars/*file controllers.WebJarAssets.at(file)

Fetching static content from webjars

As all references to libraries used are already collected to single template file we just need to use /webjars Url instead of /public when getting required libs.

Main template view is at app/views/main.scala.html, and here one need to comment out static content and enable webjars content.

        @* no more direct static jquery from /public *@
        @* <script src="@routes.Assets.at("javascripts/jquery-1.9.0.min.js")" type="text/javascript"></script> *@
        
        @* resources thru /webjars *@        
        <link rel='stylesheet' href='@routes.WebJarAssets.at(WebJarAssets.locate("css/bootstrap.min.css"))'>
<script type='text/javascript' src='@routes.WebJarAssets.at(WebJarAssets.locate("jquery.min.js"))'></script>

Test changes

Main template is getting content element as optional variable.

@(title: String)(content: Html)

You can now wrap content inside Twitter bootstraps container using class container.

    <div class="container">
           @content
     </div>


Summary

Dependency management for javascript makes it easier to work together in teams when it's possible from build definitions to see which versions of javascript libraries are in use and they can be changed once for all developers thru shared dependency management mechanism. 

Example of Webjars usage where listed steps have been committed can be seen here

https://github.com/nikkijuk/smooks-play2-xml-to-jpa