Blog

Play! Framework is getting a lot of praise. It is growing in usage and popularity. You can spot presentations about it at conferences, numerous blog posts etc. Even I praised my favorite features of the Play! Framework couple of months ago, My Top 5 Play Framework Features. There is so much positive feedback about it, that I thought it would be a bit refreshing to list the features (um, “un-features”?) that really get on my nerves. Here is my list of Play! un-features that limit my productivity, encourage me to read slashdot.org, and really irk my inner geek…

Application Startup Time Grows with Application Size

If you create a new application in Play! and start your app via play run then it takes about 2 seconds for the application to start. Basically just the time to switch to your browser and hit refresh. Once your application grows in size the startup time also grows. Our application starts for 28s in development mode (on my MBP with a SSD). This is already enough time to take a quick peek at your Google Reader. Of course the same is true for any JEE application, at first they are blazingly fast but as time goes on the startup times just grows and grows.

Reloading 3rd Party Library Code

Play! Framework applications have support for really quick turnaround because a large part of the application code changes can be reloaded instantly. So you add a method, change params and you don’t need to restart the app. This is all freakin’ awesome, but the moment you happen to develop a library that you are using within your application, you need to make room for restarts. Every code change then requires a restart. Not so happy anymore (let me find my jrebel.jar file!)

Memory Hog

Play! Framework templates are quite the memory hog. You might not notice it in the beginning, but once you have some larger pages and more users, then you will see a spike in memory consumption. This is due to the design of sub-templates. The sub-template is read into a String variable on every request that uses it. This will spike memory usage to the effect of the HTML file size. You can bypass this by giving your app more memory, having smaller templates and moving static content into static files instead of templates. There is also a more effective memory usage on the way in the 1.2.x branch.

Fear of Upgrade

Upgrading has been a bumpy ride so far, (the minors not so much) and the leap from 1.0 » 1.2 was quite scary. Our tests started failing left and right once we packaged our application. We stumbled upon quite a few  bugs and the choices in the end were to either use our custom build of Play! framework, or downgrade. We chose the first option. Now another major version is looming and a lot has changed again–check out the graphics at the 2.0 page. I’m afraid that our products will need a major overhaul if we want to get on to the next bandwagon. It just scares me.

An Issue Here and There

Play! Framework is guaranteed to surprise you when you least expect it. Just the other day I got a report from a colleague, saying that he got a verify error from Play! code. Ok, great. What can I say, try to reproduce and file a bug report? Or what about these:

  • You’re programming some feature and suddenly you start getting ClassCastExceptions. Oh well, I restart and I’m unable to reproduce. Not enough for a bug report, but there seems to be something fishy with Play! Framework reloading and Jobs. Oh well, lets hope it won’t happen again any time soon.
  • Everything is super until one of the Jenkins nodes is showing failing tests. You dig for couple of hours and you find there is special handling of a folder with a dot preceding it, finally resolved.
  • You find a controller method that produces OutOfMemoryErrors because of the dark bytecode magic that is happening behind the scenes. You’re able to reproduce it, but when submitting a bug report you try to reproduce on an empty application, which just won’t happen. You add a @ByBass to your own method and the problem goes away. Argh!

These small issues that pop up suprisingly end up stealing confidence and time. You start doubting the underlying system and lose the edge that this tool is supposed to give you. Just imagine the problems you will stumble on once Python, Groovy, Ivy is replaced by sbt, Scala, Akka.

So why do I still use Play! Framework?

When writing this piece @ekabanov asked my why on earth are using this framework then? My answer was, well, we would have just as many issues with any framework out there, but the nature of those issues would probably be different. You will always stumble upon bugs, you will always have problems when the application grows in size, and, of course, you will have problems when upgrading your dependencies. So far, there is nothing to be done.

I’d love to hear about your pet peeves with Play! Framework – please leave your comments below!

Last week was pretty good, thanks for asking. We’re all booked up for JavaOne (come geek out with us at booth #5510, and get a free JRebel or LiveRebel license) and the Jenkins User Conference in San Francisco in early October, and persistently edging towards our 1.1 release planned for the same time. Today we are releasing the first public version of it, Milestone 2. The release candidate is planned for next Friday. The main features of the 1.1 branch is full control of the application lifecycle. This means you can use LiveRebel to do your initial deploy, updates and undeploy. Also the CLI has matured a lot and has more *nix like tool features. For a complete changes check out the changelog. You can grab this release from the LiveRebel archives page.

While planning my trip to San Francisco for JavaOne (catch me there for a beer), I saw that there is a Jenkins User Conference coming up October 2nd, 2011, just prior to JavaOne. As I was signing up for the event, I started thinking that we’ve been using Hudson/Jenkins for years now. Through the years, certain Jenkins features/plugins have really paid off and been life savers for getting higher-quality software out quicker. So I thought, why not share this with you? Here is a list of my own and the team’s top 10 must-have Jenkins features/plugins.

(more…)

So, you’ve got Jenkins running nicely, and you’re proud of your Continuous Integration environment, but you’re looking to move towards Continuous Deployment. Today we’re announcing one step in that direction: combining Jenkins with LiveRebel.

Just a quick reminder, LiveRebel is a tool to manage your production updates. This means that instead of experiencing downtime or longs hours of session drain during the update you get instant, session preserving, no downtime nor OutOfMemoryError experiences. You also get to rollback changes instantly. Now imagine orchestrating this from your favourite continuous integration tool.

In May we released LiveRebel 1.0, and then went on to making it easy to configure and setup in different environments. We’ve covered how to use the CLI to script LiveRebel with bash and how to manage clustered Glassfish installation to run instant updates. Now we have turned to managing your deployments with your Jenkins/Hudson continous integration server.

You can now install the LiveRebel Deploy Plugin from the Jenkins plugin listing. A tick of a checkbox and a restart to your Jenkins installation is all that’s required. We’ve also published a How To Setup LiveRebel Deploy Plugin for Jenkins/Hudson doc, for your setup pleasure :). The plugin lets you run continuous deployments from Jenkins. This means you can turn most of your deployments into instant deployments that preserve state and don’t cause OutOfMemoryErrors.

Next features for the plugin are: support for Hudson (currently the installation is a bit more complicated) and the ability to use LiveRebel for the whole app lifecycle (currently we fallback to Cargo deploy plugin for initial deploy and not supported deploys). Stay tuned for updates!

It’s not surprising that directly after the release of LiveRebel 1.0 last month, we’ve been working hard on get the next version of LiveRebel ready – v1.0.1. To briefly sum up, we have been working on:

  • Support for more Java EE Containers – WebSphere, WebLogic
  • Real-life testing of 10GB+ of WAR files
  • Started working on a Jenkins/Hudson plugin
  • LiveRebel Scripting

Support for more Java EE Containers

Our main focus in this release has been to add support for more Java EE containers. This job involves adding the beta containers into our test suite and creating container-specific tests. Of course, these tests need to earn a PASS before we can take a container out of beta. With this release we bring IBM WebSphere and Oracle WebLogic fully out of the beta phase.

Real-life testing of 10GB+ of WAR files

At the same time, we’ve been using a lot of our internal tooling to analyze a large number of WAR files. We’ve gone over 10GB of web application versions to test our tooling on real-life projects. The results from this will be released in due time, once all the info is analyzed. This process has brought couple of fixes to our command-line tooling.

Jenkins/Hudson Plugin for LiveRebel

During this time we started work on the Jenkins/Hudson plugin. This means that you can use LiveRebel to deploy artefacts built with your CI to staging or production. This initiative is still in beta right now but this also has introduced some new internal features and fixes.

LiveRebel Scripting

One other direction we are moving to is the scripting of LiveRebel. We’ve released CLI documentation and also a how-to article on scripting LiveRebel with Bash. This department will have some new features in the following release and there are also articles in the pipeline on how to script against our REST API.

All in all, it has been a really busy month for us. Besides moving into a new office with Starcraft TV and hiring like crazy, we’ve been able to bring many fixes and changes to LiveRebel. Checkout the full changelog and head off to download your copy – LiveRebel is still free for 90 days here!

One of the features that we are looking forward to more people learning about in LiveRebel is the command line interface (CLI). You can run most of the LiveRebel functionality from the command line. There is a manual that covers most of the CLI aspects available on our LiveRebel documentation page. In this article we will use those bits and pieces to write a script that will run automatic updates.

We will be using bash as the scripting language. The end script is available from the LiveRebel Scripts repository.

Some assumptions:

  • We assume that you have installed and configured LiveRebel, and you have access to the LiveRebel lr-cli.sh script (in the LiveRebel installation’s bin directory).
  • We assume that you have a script to run a full redeploy/restart when LiveRebel does not support the change.

You’ll need a LiveRebel authorization token found inthe LiveRebel Web Console as shown here:

Let’s start with writing the script by defining the TOKEN and LiveRebel home directory and the lr-cli.sh locations.

#!/bin/bash
 
# LiveRebel Command Center token
TOKEN="ad7af931-3cf6-4000-967d-925dcfc44955"
# LiveRebel Installation Dir
LR_HOME=/Users/toomasr/Downloads/liverebel
CLI_SCRIPT=$LR_HOME/bin/lr-cli.sh

Next, let’s use the 1st parameter to the script as the WAR file that needs to be uploaded to the LiveRebel Command Center. We will take the output of the upload command into a variable called RESULT and later on use that to parse the response.

FILENAME=$1
RESULT=$($CLI_SCRIPT -token $TOKEN -url localhost:9001 upload -file $FILENAME)

Now to parse the response. The response has 3 different outcomes and based on the result we are also interested in the name of the application (the application name can be different from the WAR archive name, it is defined in the liverebel.xml file inside the WAR archive).

  • Unable to connect to LiveRebel Command Center
  • Application has already been uploaded
  • The upload was a success
if [[ $RESULT == *refused* ]];
then
    echo "Unable to connect to LiveRebel. Are you sure your server is running?"
    echo "Exiting..."
    exit 1
elif [[ $RESULT == *ERROR* ]];
then
    VER=`echo $RESULT | grep -o "Version [^a-z]*"`
    VER=${VER#Version }
 
    APP=`echo $RESULT | grep -o "of application .* already exists"`
    APP=${APP#of application }
    APP=${APP% already exists}
else
    VER=`echo $RESULT | grep -o "Version: .*"`
    VER=${VER#Version: }
 
    APP=`echo $RESULT | grep -o "Application: .*Version: "`
    APP=${APP#Application: }
    APP=${APP% Version: }
fi

If everything went well, then by now we have either uploaded the WAR file or it already exists on the LiveRebel Command Center. We’ve also extracted the name of the application and the version. The next step is to figure out the active version of this application. We will later on use this information to run the compatibility test.

# find out the active version
RESULT=$($CLI_SCRIPT -token $TOKEN -url localhost:9001 vers -app $APP)
ACTIVE_VER=`echo $RESULT | grep -o "Active: .*"`
ACTIVE_VER=${ACTIVE_VER#Active: }
 
if [[ "" == $ACTIVE_VER ]];
then
    echo "The application is not deployed to any of the servers. Not doing anything"
    exit 1
fi
 
echo "Active ver $ACTIVE_VER, uploaded $VER"
 
if [[ $VER == $ACTIVE_VER ]];
then
    echo "You are trying to upload the same version. Not doing anything"
    exit 1
fi

We have the active version of the application now. Now let’s find out if the update from the active version to the version we just uploaded is supported by LiveRebel or not. If it is compatible, then run the update – otherwise use your fallback solution.

RESULT=$($CLI_SCRIPT -token $TOKEN -url localhost:9001 diff -app $APP -from $ACTIVE_VER -to $VER)
 
if [[ $RESULT == "Compatibility: compatible" ]];
then
    echo "Versions are compatible. Activating version $VER"
    $CLI_SCRIPT -token $TOKEN -url localhost:9001 update -app $APP -ver $VER
else
    # your own custom script to run the redeploy
fi

Voila! and we’re done. This article serves as an example how to interact with LiveRebel Command using the CLI. Your mileage may vary and you might want to invoke the LiveRebel script from your own master script. If that is the case, you will need to change a few things here and there. But just refer to the CLI documentation and use the commands one by one.

PS! We are working on a Jenkins/Hudson plugin that would do all this automatically. In case of incompatibility it would either use the Cargo plugin as fallback option. This plugin is available from the LiveRebel Deploy Plugin repository.

As we enter the final race to the stable release of LiveRebel we’re happy to announce that  the LiveRebel 1.0 RC2 have passed all tests and has been uploaded to liverebel.com from the ZeroTurnaround Tartu labs.

This release doesn’t introduce any new features. We’ve fixed several small issues, run our product on an even larger testsuite and tweaked the UI here and there. If you are testing out LiveRebel be sure to upgrade. We are on track for 1.0 release on 17th May, stay tuned.

We have just released the last milestone of LiveRebel Beta, M12. We will continue with release candidates from this point on. We were able to complete all the features critical for 1.0

  • We redesigned the UI and reworked UX (thank you guys at Fraktal)
  • We reduced runtime performance overhead to under 3%, as measured by SpecJVM2008 (a 5x improvement over previous milestones)
  • We upgraded internal Play! Framework to version 1.2

The only feature that we have yet to deliver is LiveRebel Failover. You can have multiple Command Centers in charge of your cluster. This ensures that you don’t need to make changes to your cluster when something happens with your command center machine. This is something planned for RC1 due Friday the 29th.

In the meantime, check out our survey, How do you update your Java EE app in production? It’s a single page that takes a couple minutes to fill out…plus it lets you try to prove Jevgeni, our CTO, wrong about his assumptions!

Other than that please get a shiny new copy of LiveRebel at our download page. Be sure to do a fresh installation.

For couple of weeks now, I’ve been looking into Continuous Integration with multiple branches with Jenkins/Hudson. I’ve searched the intertubes, talked to friends, colleagues and other nerds out there.

My greatest discovery was that although CI is about committing, pushing and getting feedback often (i.e. the CI cluster provides you with feedback that your workstation could never give you in the same amount of time), the true purist CI actually has one more requirement — that the team needs to work on the same baseline.

I wish there was some kind of tooling for not-so-purist CI and I’ll try to explain why…

First, the non-technical view of the problem

I work on products that are distributed as downloads. After a person downloads, it is up to them to update to a newer version if they want to. So I can’t push out quick fixes that get deployed to clients automatically — the software will inform the user when a new version is available, but there are no guarantees that they will upgrade.

This means we need to take extra steps in our quality assurance (QA). In contrast, if your product is offered as a service then most of the time you can push out changes and they are visible to all clients out there. No such luck for me. This limitation puts extra attention on QA.

We have created two main branches, DEV and STABLE. DEV is the mainline that we share. The CI cluster provides extra quick feedback on this branch. It runs a test-suite of our software, testing it on a handful of JEE containers out there (e.g. Tomcat, JBoss and Websphere series). If the tests succeed, then the code is pushed to the stable branch. The CI cluster then runs the test-suite on 50 container versions.

This approach would take the pressure to have a machine or OS that supports so many test environments away from devs. They get quick feedback if their push has broken any container that they did not test locally (e.g. “Did my Resin changes break anything on Glassfish?”)

Okay, I seem to have stuff figured out, so what’s the problem then? Well, if developers want to live in their own branch for a while and still get the benefits of automated testing on a large variety of environments, then they won’t be able to do that. They are not CI engineers.

Technical view of the problem

Jenkins/Hudson uses a notion of jobs. A job is something that is usually tied to a VCS URL and then gets built (run) when there is a change in the VCS repository. The build can do anything, from executing shell scripts to sending out tweets of the status of the build.

The build can produce all kinds of results. In our case, we use Maven and Maven artefacts are the results. The artefacts are stored in one repository for the DEV branch, and in another for the STABLE branch. This is because multiple DEV branch jobs can re-use prebuilt snapshots that won’t conflict with STABLE snapshots.

There are two set of jobs. The DEV jobs and the STABLE jobs. There are two because the VCS urls differ and the maven repositories differ and now we have a problem. The two set of jobs needs to stay in sync. So if we change a job in DEV (e.g. add a new step), we’d want to change a job in STABLE and vice versa.

If devs want to live in their own branch, they need to sync any jobs that they duplicate. And now the job management is just getting out of hand:

  • They start the duplication of jobs
  • They try to keep them in sync
  • They start debugging the jobs (e.g. “Why is there a port race between SAP NetWeaver and OC4J9?”)
  • The delete the jobs after integration

Instead of developing the feature, the dev is now becoming a CI engineer. Shouldn’t he just get fast feedback from a large variety of environments without any hassle?

Solutions

The many posts that I’ve read through suggest writing the tooling for branch management. Shell scripts and ANT tasks that duplicate jobs on the filesystem level are popular. Scripts using the Jenkins/Hudson API are also a good choice.

But what if I don’t want to write another set of tooling? This is something that should be provided by the CI software I’m using. I’m sure I’m not the only one out there using branching and wanting CI support for it.

The CI purists will say that I’m doing it wrong and that I should either drop the feature branches or live with the problems. But does it have to be that way?

I’d really like to see a Jenkins plugin that will understand multiple branches, multiple Maven repositories and just deal with the problem. If CI necessarily implies a single branch, maybe we can change the name of these servers to Continuous Integration and Build Automation servers and we could throw out the implication?

We’ll have to wait and see…

Materials used

For a year I’ve been working on two projects using the Play! Framework. The JRebel License Server and LiveRebel. I was evaluating different frameworks for these tasks and it boiled down to a choice between Struts and Play! Framework. Play! seemed the risky, cool, rebellious choice, while Struts was something more like the work horse (somewhat old) who delivers for sure. After some debate within the team we took a chance and went with Play!. During this time I’ve grown to love some features of Play! more than others and would like to share the love.

My Top 5 Play! Framework Features

Jobs

Play! framework jobs provide a way of running program logic “in the background”. Play! will take care of the lifecycle and the timings. For example if you need something to run every 5 minutes you will use an annotation @Every(“5min”) and the job will be run every 5 minutes. I’ve included an example called MemoryUsageLogger which logs the memory usage of the application. Its just dead simple.

@OnApplicationStart
@Every("5min")
public class MemoryUsageLogger extends Job {
  private volatile boolean maxPrinted = false;
 
  @Override
  public void doJob() throws Exception {
    Runtime r = Runtime.getRuntime();
 
    long total = r.totalMemory();
    long free = r.freeMemory();
    long used = total - free;
 
    if (!maxPrinted) {
      Logger.debug("Used: %dM Free: %dM Total: %dM Max: %dM", m(used), m(free), m(total), m(r.maxMemory()));
      maxPrinted = true;
    }
    else {
      Logger.debug("Used: %dM Free: %dM Total: %dM", m(used), m(free), m(total));
    }
  }
 
  private static long m(long bytes) {
    return bytes / 1024 / 1024;
  }
}

Templating

So far I’ve used JSPs (old and XML syntax), Jelly (Hudson plugins), XTemplate and Smarty for PHP as templating engines. I’ve never felt productive in these, writing custom tags that choke when changing the container, fighting with bloated XML or even just learning an obscure templating expression language has not been fun.

Play! template engine uses Groovy as an expression language and also a tag system for reusable components. Groovy is a clean, intuitive, powerful language which is really easy for Java devs to pick up. I also like that it is a separate, well established project vs something that is only meant for templating.

#{list items:resources,as:'res'}
  #{if res.directory}
    <tr class="directory collapsed" rel="${res.id}" parent="${res.parent?.id}">
      <td><a href="#">${res.name}</a></td>
      <td></td>
      <td class="right">${res.lastModified == null ? '(unknown)' : res.lastModified.format("yyyy-MM-dd HH:mm")}</td>
    </tr>
  #{/if}
#{/list}

This all comes with great error messages, even for the templating code. You can quickly tell where you’ve made a mistake. I just hope the templating language will be supported by Eclipse to provide content assist and highlighting.

URL mappings and redirects

Your controllers in Play! contain ton of static methods that adhere to the URLs of your application. For example, if you need to show something for a URL /contacts/list you would implement a method list in a controller contacts (this is the default naming convention that can be changed). Or if you want a page to show an actual contact you would have a method showContact and it will get mapped to /contacts/showcontact.

What if I want to redirect from the list page to a show contact page when there is only a single contact to show? In your Java code in the list method just invoke the showContact method, it’s going to be an HTTP redirect. So easy and readable in Java that it is scary.

Testing

Automated app testing is a difficult subject, there are tons of approaches out there and its all about you picking a couple and trying to use them with your app written in framework X. Play! has a different approach and it comes bundled with a slick interface to run unit, functional and selenium tests against your app. As testing is something that is so easy to “forget about” then something halfway enforced is really welcomed. Besides automating this you can use the same interface while developing vs configuring the tests to run from your IDE or ant/maven/shell.

Quick Turnaround

We at ZeroTurnaround are really into developer productivity. Our flagship product JRebel lets you change your application code and just hit refresh in your browser and you’ll see the changes instantly. Play! framework offers something similar. I have not read enough source code but it seems that with custom extra metadata (see your app’s tmp/bytecode/DEV), a stateless model and the custom runner (play run) they will give you the power of changing code on the fly. If they don’t support the change they will restart your app automatically for you. This is actually a really big thing compared to other frameworks out there.

Conclusions

Play! framework is packed with cool features and this is only my top 5. Of course Play! is no silver bullet and it does have its own set of problems, but that is something for another article. So far Play! has proven to be a productive and intuitive environment to develop in. What are your favourite features of Play!?


Toomas RömerToomas Römer is the co founder and product lead of ZeroTurnaround. Once a Linux junkie, he was fooled by Apple into proprietory OS and devices. He is a big fan of JUGs, OSS communities and beer. He blogs at dow.ngra.de, tweets from @toomasr and also runs the non-profit chesspastebin.com website. In his spare time he crashes Lexuses while test driving them, plays chess, Go and Starcraft. Looks can fool you; he will probably beat you in Squash. You can connect with Toomas on LinkedIn.


Older Entries »

Join the Rebellion Facebook Twitter RSS feed