Tuesday, February 28, 2012


Part 2: Continuous Integration (CI) with Jenkins for a application using Play Framework 

In CI Part 1 I have shown you how to configure Play Framework, how to configure the Jenkins Play Plugin. In this post I will show how to post your modules to Nexus server, how to use the repository in the dependencies file, chained dependencies, continuous integration and auto deploy.

Intro

When working on an application in the early stage you will go on and build the requirements. But as the application grows you find necessary to split your application in different components. In time after you build more and more applications you realize that those components can be used across different applications.
To achieve this Play framework provides us with modules. A play module is nothing more than a play application with a small difference that it doesn't have an application.conf file and it is not meant to run on its own, it needs to be included in a containing application. You can read more details about pay modules and how to use them in this fine article: Divide and conquer play framework modules.

Modules and Apps

Usually when working with play you will have a play application and several modules. In the bellow diagram you can see and example. The "MyWebApp" applications depends on three modules:
MyWebApp and its dependencies

To create a play application I'll use the following command:
    > play new MyWebApp

Then I will create my modules:
   > play new-module Module1
    > play new-module Module2
    > play new-module Module3

Then folder structure would look like this:
/myProjects/
    /yoda/Module1-1.0
    /yoda/Module2-2.1
    /yoda/Module3-3.0
    /MyWebApp
  
So this is it. You have a web app ready and a couple of modules, but how to use those modules in your application? Check the next chapter.

Configure dependencies

Each Play application, in conf folder has a file called dependencies.yml used to dependency management for your application. 
For MyWebApp the dependencies.yml should look like this:

# Dependencies

require:
 - play

This is simple, but I still don't have the the modules in dependencies, so I can define repositories. Because my modules are in the local files system I will define a local repository, so the dependencies.yml will look look this:

# Dependencies

require:
 - play
 - yoda -> Module1 1.0
 - yoda -> Module2 2.1
 - yoda -> Module3 3.0
repositories:
 - MyLocalRepo:
    type: local
    artifact: ${application.path}/../[organization]/[module]-[revision]
    contains:
      - yoda -> *

When running the play deps --sync --clearcache command, when resolving the dependencies the dependency resolver will search in folder /myProjects/ for organization yoda/ for modules Module1, revision 1.0, Module2 revision 2.1 and Module3 revision 3.0, as declared in the dependencies.yml require section. 
I have only explained the basic and practical stuff, the play dependency mangement has more details on dependency management.

Post to Nexus

So far so fine, but you need to have the modules in the local file system. Probably you will work with a SCM  like GIT or SVN and you will need to checkout all modules in your file system and create all the folder structure. On top of all you will need to constantly update your code. That is a lot of overhead if you ask me:  Nexus to the rescue.

Before showing you how can you post to Nexus I will explain how the dependencies.yml file should look for a play module.

# Module dependencies file

self Module1 1.0

require:
    - play 1.2.4

The first line is the module name declaration with the module revision number, then we have the required section where I have declared play and play version. The play version is optional but when running the play build-module command, it will ask for play version.

A couple of days ago I have found this snippet. Its a play command that posts a module to a repository. This play command requires the python library poster. After you have installed that python library the command is easy to install and use. Download the nexus.py file in ${play.path}/framework/pym/play/commands/ and that is it, you can use just like any other play command.

How to use Nexus command:

First you need to add in the module application.conf a couple of nexus configurations:

nexus.server.url=http://myNexus.server.org/repo/artifact-group
nexus.server.user=MyUser
nexus.server.password=password

Run the following commands:

play build-module //creates [module]-[version].zip in folder [module]/dist

Next run command:

play nexus-commit [-a] // -a: pushes the file without confirmation

The command will look for the [module]-[version].zip file in dist folder and post the file to nexus at address http://myNexus.server.org/repo/artifact-group/[module]/[version]-SNAPSHOT/[module]-[version]-SNAPSHOT.zip

Configure a chained repository

With that nice nexus play command I have posted my module to a repository and now I can configure the dependencies for MyWebApp to use the nexus to retrieve the module dependencies, so I don't need all my modules in my file system(only the ones I work on) and I don't bother with doing constant updates on modules that I don't work(We will see why in the next chapter when I'll show you how to configure Jenkins).
So the dependencies.yml will look like this now:

# Dependencies

require:
 - play
 -  artifact-group -> Module1 1.0
 -  artifact-group -> Module2 2.1
 -  artifact-group -> Module3 3.0

repositories:
 - MyChainedRepo:
    type: chain
    using: 
      - LocalModules:
          type: local
          artifact: ${application.path}/../[organization]/[module]-[revision]
      - MyNexus:
          type: http
          artifact: http://myNexus.server.org/repo/artifact-group/[module]/[version]-SNAPSHOT/[module]-[version]-SNAPSHOT.zip
    contains:
      - artifact-group -> *

This chain dependency will look for the required modules in the local file system and if are not found then it will download them from nexus.

Continuous Integration

In CI Part 1 I have explained you how to create a Jenkins job for a play application and a play module. I want to post all my modules to nexus using Jenkins. 
The solution is very simple, I will create a Jenkins for each of my modules and besides the standard commands:

play deps --sync --clearcache
play precompile
play auto-test
play build-module

I will add the nexus command to post the module to nexus

play nexus-commit -a

This is it, your latest changes are available on Nexus.

Auto-deploy for MyWebApp:

I want all my changes to be available for testing as soon as possible so you can configure autodeploy  for your web app. You just need to create a Jenkins job, and add this commands:

play deps --sync --clearcache // clear all my cached dependencies and synchronize them
play precompile // If it's a problem in the java classes then the job will fail
play auto-test
play restart --http.port=<port>

When working on a application that uses Play you will notice that all your modifications are available just after you've saved the file you have modified. Well, almost all modifications because after a modification in application.conf, you will need to restart the server.

Conclusions

Well, this is about it related with continuous integration. I hope it helps and I am waiting for feedback.

P.S. I am also working on some code analysis with sonar but because Play Framework doesn't follow the "Java Best Practices" rules, sonar rates are small for the code.

Sunday, February 19, 2012

Part 1: Continuous Integration (CI) with Jenkins for a application using Play Framework 

Intro

A few months ago I have found Play Framework and I started using it to develop a web project. Before using play I was used with Struts, Spring MVC or other web frameworks and also I was using maven to build and pack my applications.
In a large scale project it is a need to have CI configured and automatic deployment. The CI server I use is the open source server Jenkins. If you don't have Jenkins installed and configured check this link for help.

Install play framework

You need to download Play unzip and add the play location into path. If you know how to add a folder to the path then skip the next lines and check how to install the play plugin for Jenkins.
I did the configuration as root:
  1. Unzip play:
    unzip play-1.2.4.zip /destination
  2. Create symbolic link to play(This will help us at version upgrades):
    ln -s /destination/play-1.2.4 /destination/play
  3. Add play to path:
    vi /etc/profile
    The command above will open the profile file for edit.
    Add the following at the end of the file:
    PLAY_PATH=/destination/play
    export PLAY_PATH
    PATH=$PATH:$PLAY_PATH
    export PATH
  4. Logout so the paths are updated.
There you are, play is installed and added to path; it is ready to use

Install Play plugin for Jenkins

Got to Manage Jenkins -> Manage Plugins - > Available Plugin, check on playframework-plugin and install. Restart webserver or Jenkins server (depending if Jenkins is deployed in a webserver or is started as a service). Or you can install it manually by downloading the Jenkins Play plugin.

Configure Jenkins job

Ok, we have installed Play! Framework and configured in path, we’ve installed the Play Plugin for Jenkins, let’s see how we create a Jenkins job for a play project in a few easy steps:
  1. Click on ‘New Job’ in Jenkins dashboard.
  2. Choose a name for your project then click on ‘Build a free-style software project’.
  3. Configure the Play! Application path.
    Jenkins checks out the code from a repository into a working directory. Usually the working directory will be /root/.jenkins/jobs/MyPlayProject/workspace but I have changed the location because when trying to zip the play module using the play build-module command, for some reason when creating a zip file in a hidden directory nothing is written in it. So because of the above motives I have changed the Job working directory to /jenkinsjobs/MyPlayProject/workspace.
    In the workspace folder you will have:
    workspace
    api
    my-play-project

    Check Play! Application path and fill in the path field wih ‘my-play-project’.
  4. Configure source code management GIT/SVN.
  5. Configure Build. From dropdown ‘Add build Step’ choose Play.
  6. Configure play commands:
    I usually add the following commands when building my play modules:
    deps --sync --clearcache
    auto-test
    build-module
    Check this cheat sheet to test other play commands.
  7. save and you are done.

Coming next...

Next I'll show you how you can configure code analysis with Sonar, how to upload your modules to a Nexus and create a dependency chain for your projects.

Check Part 2: Continuous Integration (CI) with Jenkins for a application using Play Framework.