Nick Carroll Software Professional

One click deployment with Maven and Bamboo

A while back I wrote about achieving continuous deployment with one-click deployments. I didn’t provide an example for that post as I mostly wrote about why you need to achieve continuous deployment. Here I will follow up with a simple example of how you can achieve continuous deployment.

Continuous deployment is quite easy to setup if you are using a typical Maven project structure and Bamboo as your continuous integration tool. Also I am assuming that you want to deploy your application to a tomcat server.

In your pom.xml file add the following configuration so that you use the Tomcat plugin for deploying your application to http://hostname.com/app. Change the path, url, and server configurations to suit your needs.

<project>
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>tomcat-maven-plugin</artifactId>
        <configuration>
          <path>/app</path>
          <url>http://hostname.com/manager</url>
          <server>deployment.server</server>
        </configuration>
      </plugin>
    </plugins>
  </reporting>
</project>

Also make sure that your .m2/settings.xml file contains the following for authenticating with the Tomcat manager.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

http://maven.apache.org/xsd/settings-1.0.0.xsd">

  <servers>
    <server>
      <id>deployment.server</id>
      <username>tomcat</username>
      <password>password</password>
    </server>
  </servers>
</settings>

In Bamboo create a new pan for your project. I tend to give this plan the name “Promote to Production”. Configure the Builder goal for Maven to run clean tomcat:redeploy. I also only allow a specific user to trigger this plan so that not everyone has permission to deploy into production. Finally, configure the build strategy to run manually, so an authorised person can click on the Build plan button in Bamboo to deploy the application.

Once set up the above instructions will allow an authorised person in Bamboo to click on a single button to deploy into production. Leveraging your continuous integration tool for deployment allows you to archive deployment artifacts such as your WAR files in the case where you have to revert to a previous version.

Last month at ThoughtWorks

I was sifting through my blog entries during the holidays and came across my post three years ago about my first month at ThoughtWorks. After reading it I felt it needed an update, otherwise I probably wouldn’t have left the company if the list was still accurate. My last day at ThoughtWorks was 24th December 2009.

  1. Other ThoughtWorkers: I have had the chance to work with some of the most incredible software developers that I have ever met. These guys and gals really know how to thrash a keyboard around when pumping out quality code. It has to be said that working with really talented individuals makes work very enjoyable. Which goes to show that Roy’s social experiment is still going strong after all these years.

    The people at ThoughtWorks are certainly a great bunch of people. I would still rank working with many of the fine folks at ThoughtWorks as one of my best experiences. However, many of them have since moved on to greener pastures.

  2. Ruby is such a cool programming language and I am so glad that I am working at a company that has completely embraced it. Ruby has been around in the US and Europe for a while, but it is still relatively new in Australia. I am waiting impatiently for the Aussie tech industry to catch up so that I can finally work on a Ruby project.

    Meanwhile I have been ramping up on my Ruby skills, and there is no better place in Australia for learning Ruby. We have some of the best Ruby developers working in Sydney at the new ThoughtWorks Studios, and they open their doors after work each week for us to work on a Ruby project with them.

    Sadly, I never got to write a line of Ruby code that made it into production. It was only ever Java code. Also, ThoughtWorks Studios is no longer based in Sydney.

  3. Agile is certainly an interesting approach to developing software. I have already been thrown head first into a large agile software development project, and I am already hooked on the agile koolaid. Over the weekend our client deployed the first release in time for a public launch of their system. It is the first large scale project that I have worked on, and it was a success right off the bat. The release was completed on-time, on-budget, and with 5 times less defects than any of their previous projects. Being part of a team that produced a result like this certainly made my first month a memorable one.

    I am still a strong advocate for Agile software development. I was never part of a project that failed to deliver, and I am extremely proud of this success.

  4. Open Communication: I have been amazed with how open the lines of communication are within the company. In the first two weeks I had met Martin Fowler our lead scientist, coffee with Bruce the Australian MD, and beers with Roy Singham the founder of the company. They all made themselves available to talk about agile, corporate strategy, and whatever the next big thing might be. I thought it was cool to be able to hang out with these guys. There aren’t many companies out there that have corporate leaders that like to hang out with their employees and have a general interest in them.

    Communication is not as open as it used to be.

  5. Geek Night is just one of many ThoughtWorks events that helps to facilitate knowledge sharing within the company. It is an after work event where developers head back to the ThoughtWorks office for a night of geeking out in front of a computer. We learn a new programming language whilst downing copious amounts of Coke Zero and rice cracker snacks.

    Geek Night rarely happens. I tried my best to inject some life into it with the Functional Programming and Groovy user groups, but the interest just wasn’t there.

  6. Free food: I have put on a couple of kilos since I started work. It has to do with all the lunches and dinners that the company has put on. They keep a fridge stocked with beers, wine, soft drinks and fruit juice. As well as bowls of fruit and cupboards filled with biscuits, chips, and chocolates. Best of all they have a tab going for free coffee at a local cafe!

    There is still free food on Fridays. The coffee tab at the local cafe got replaced with an in-house coffee machine.

  7. Consulting Dojo: There is one catch to the free food, on Fridays lunch is provided to attract all the ThoughtWorkers to the office to listen to one of our colleagues present on a consulting related topic. The presentations have been very interesting, and there is always a good turn out. The dojo is another example of knowledge sharing within the company.

    The dojos are still around, but in a lighter form. A couple of presenters are given 5 minutes to present on a topic that ranges from cool stuff that happened on a project to how to use a Mac.

  8. Training and book budgets: Each ThoughtWorker is provided with their own personal budget for training and purchasing books. Essentially we are responsible for our own learning and personal development. So we can choose whatever course or conference we want to attend. There is just so much support for our career development.

    The training and book budgets are still around. There was a period when the training budget was reduced, but it is back to where it was. I only ever got to use my training budget in my first year, after that I found it hard to find time for training as I was always on a project and focused on delivery. However I made good use of the book budget. It is something that I will certainly miss.

  9. Brand new Dell Latitude D620: It isn’t a Mac, but I have been very impressed with this piece of hardware. I really like the widescreen display, Intel Core Duo processor, and the feel of the keyboard. It also doesn’t get that hot from extended usage. It is the first Dell I’ve used, and I’m very happy with it.

    Would you believe that the Macbook Pro is now the default laptop? It was a sad day when I had to return my new 15 inch Macbook.

  10. Mobile phone and home broadband: This is a nice perk, having your company pay for your mobile phone and home broadband bills. I can finally afford ADSL2!

    You still get a mobile phone and broadband budget. So you can sign up for an iPhone when you join.

This will be my last post on ThoughtWorks as I close this chapter of my life.

Agile Australia 2009 iPhone App

I have been working as part of a team at ThoughtWorks to build an iPhone app for the upcoming Agile Australia 2009 conference. It has been an anxious wait for Apple to approve the app, but it was a thrill when that email finally came through. I am pleased to announce that the Agile Australia 2009 iphone app is now available for download at the iTunes store for free! If you are attending the conference then this companion app will keep you informed of the schedule, provide feedback, follow the hot sessions, find your rooms, and tweet about the talks.

Using StringTemplate as the view engine for your Spring MVC application

I wish I never discovered Django templates because I shudder every time I have to use Freemarker or Velocity for my Spring MVC applications. Fortunately there is an alternative. You can use StringTemplate to generate your views in Spring MVC quite easily. StringTemplate enforces a strict separation of concerns, which therefore minimises the amount of logic that is allowed in the view, thus forcing you to do more in your controllers. Therefore your view remains purely for presentation purposes.

First things first is that you need to download StringTemplate and Antlr, and make those libraries available on your classpath. Next, extend Spring’s InternalResourceView.

import org.springframework.web.servlet.view.InternalResourceView;
import org.springframework.core.io.Resource;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.io.PrintWriter;

public class StringTemplateView extends InternalResourceView {

    @Override
    protected void renderMergedOutputModel(Map model, HttpServletRequest request,
                HttpServletResponse response) throws Exception {

        Resource templateFile = getApplicationContext().getResource(getUrl());

        StringTemplateGroup group = new StringTemplateGroup("webpages", templateFile.getFile().getParent());
        StringTemplate template = group.getInstanceOf(getBeanName());
        template.setAttributes(model);

        PrintWriter writer = response.getWriter();
        writer.print(template);
        writer.flush();
        writer.close();
    }
}

Finally, you need to configure your Spring application context to use StringTemplate to render your views.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="com.agilecognition.bookshelf.web.view.StringTemplateView"/>
        <property name="prefix" value="/WEB-INF/templates/"/>
        <property name="suffix" value=".st"/>
        <property name="requestContextAttribute" value="rc"/>
    </bean>
</beans>

Now you can organise your StringTemplate files that have the “.st” suffix in /WEB-INF/templates. For example, you might want to organise your templates as follows.

WEB-INF + templates + layout layout.st + partials header.st footer.st feedback_form.st contact_us.st

The layout.st template might look like the following template.

<html>
  <body>
    <div class="header">$partials/header()$</div>
    <div class="content">$body$</div>
    <div class="footer">$partials/footer()$</div>
  </body>
</html>

The above layout.st contains the basic structure for an HTML page on your site. You can use this one template to keep a consistent look and feel across your entire site. The layout.st template depends on the header.st and footer.st templates that exist in the partials directory.

To insert the feedback form in feedback_form.st into the $body$ placeholder attribute for your contacts page you simply create a contact_us.st template with the following line.

$layout/layout(body=partials/feedback_form())$ When your controller handles the request to display the contact us page, the controller will return a ModelAndView with the view name set to “contact_us”. The view name maps to the contact_us.st file in your templates directory. StringTemplate will render the contact_us page using the layout template with the header, footer and feedback form templates.

Achieving continuous deployment with one click deployments

It makes me very happy to see others championing continuous deployment. Apparently the developers at IMVU release into production a number of times a day, as often as 50 releases in a day. Smells like a lot of bug fixing than new features, but at the very least they have a lean process for releasing into production. I believe having the capability to release into production as often as possible is more important than having a process that draws out the length of time that it takes to release into production.

I’ve always been a fan of getting code into production as quickly as possible. Releasing into production early and often adds business value and keeps users happy. Adding new functionality that makes it easier to add items to a shopping cart for example means the business can encourage more fluid sales through a better online experience. It also means certain bugs won’t provide a detrimental user experience that would drive customers away. You will drive more customers away the longer a bug stays in production. Or if you are lucky, have one of your users get so ticked off with your application that they provide their own patch and release it for you.

My preferred approach to continuous deployment is to integrate it as part of your continuous integration (CI) build box. With Cruise or Bamboo create a build that runs an ant script that creates a branch, compiles source, runs tests, and deploys on a successful build. You might want to keep this build separate from your regular trunk builds, as you may not want to release every time someone checks code into the source code repository, especially when your team gets into a healthy habit of doing atomic commits.

Utilising your CI box in your deployment process effectively means you can release into production with one click of a button. Imagine that, one click deployment, one click that automates your quality assurance process (assuming you have a quality suite of unit, integration, and functional tests), and production artifacts such as WAR files and configuration properties for archiving. Spending time improving your deployment process and making it leaner means you can realise business value earlier and keep your customers happier.