Thomas Sundberg

November 1, 2012

A JSF web application

This post has been migrated to

Previous – Building the model

Many modern applications are built as web applications. The benefits are obvious, you don’t need to package your software in shrink-wrap and send it to your customers. Upgrading is easy, you have to upgrade the server you host the system on and that’s it.

The first user interface I will add to the rental system will therefore be a web GUI. It will be the simplest possible solution and the goal is not to build a fancy web app. The goal is to show how Cucumber can control a tool like Selenium WebDriver to assert the behaviour of the web application.

This project will be divided in two different Maven modules and it will depend on the model I just developed. The modules are:

  • jsf-main – the actual web application
  • jsf-test – a test project where the web application is automatically deployed and its behaviour verified

A parent project is added to connect the two modules.

The choice for this division is motivated in separating test and production code in a Maven build.

The first thing I will do is to setup the test module and have it to execute the Cucumber feature. I will use the same feature as for the model; my need for behaviour has not changed just because I am adding a GUI to the solution.


Feature: Rental cars should be possible to rent to gain revenue to the rental company. As an owner of a car rental company I want to make cars available for renting So I can make money Scenario: Find and rent a car Given there are 18 cars available for rental When I rent one Then there will only be 17 cars available for rental

The glue code to connect the feature above with Cucumber is also similar:


package se.waymark.rentit; import cucumber.api.junit.Cucumber; import org.junit.runner.RunWith; @RunWith(Cucumber.class) public class RunCukesIT { }

I have changed the name of the class to RunCukesIT so the Maven fail-safe plugin will include it without an explicit include in the plugin configuration.

The steps are also identical:


package se.waymark.rentit.steps; import; import; import; import static; import static org.junit.Assert.assertThat; public class RentStepdefs { private RentACarSupport rentACarSupport = new RentACarSupport(); @Given("^there are (\\d+) cars available for rental$") public void there_are_cars_available_for_rental(int availableCars) throws Throwable { rentACarSupport.createCars(availableCars); } @When("^I rent one$") public void rent_one_car() throws Throwable { rentACarSupport.rentACar(); } @Then("^there will only be (\\d+) cars available for rental$") public void there_will_be_less_cars_available_for_rental(int expectedAvailableCars) throws Throwable { int actualAvailableCars = rentACarSupport.getAvailableNumberOfCars(); assertThat(actualAvailableCars, is(expectedAvailableCars)); } }

The only differences in the test project are the help class and the Maven pom. The help class obviously need to use Selenium to connect to the running web application. The Maven pom will need to deploy the web application before it executes the test suite.

The new help class looks like this:


package se.waymark.rentit.steps; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; public class RentACarSupport { public void createCars(int availableCars) { WebDriver driver = new FirefoxDriver(); try { driver.get("http://localhost:8080/rentit/faces/create.xhtml"); WebElement numberOfCarsToCreate = driver.findElement("create:numberOfCars")); numberOfCarsToCreate.clear(); numberOfCarsToCreate.sendKeys("" + availableCars); WebElement createButton = driver.findElement("create:createButton"));; } finally { driver.close(); } } public void rentACar() { WebDriver driver = new FirefoxDriver(); try { driver.get("http://localhost:8080/rentit/faces/rent.xhtml"); WebElement rentButton = driver.findElement("rent:rentButton"));; } finally { driver.close(); } } public int getAvailableNumberOfCars() { WebDriver driver = new FirefoxDriver(); try { driver.get("http://localhost:8080/rentit"); WebElement availableCars = driver.findElement("availableCars")); String availableCarsString = availableCars.getText(); return Integer.parseInt(availableCarsString); } finally { driver.close(); } } }

It consists of three methods. This is identical to the help class I wrote earlier. There is no reference to the domain model here. The web application must be deployed and running when these methods are executed. The state of the rental system will be held on the server.

The first thing I do in every method is to create a Firefox web driver so I can use Firefox to exercise the application. The second thing every method is doing is to connect to different web pages in the web application.

When the proper page has been located each method does different things. They locate different elements in the web page and use them. As an example, the method createCars() enters the number of cars to be created in a form and then submits the form.

Obvious issues with these methods are that

  • I have hardcoded which browser to use
  • I have hardcoded where the web application is hosted

This need to be fixed, but is out of the scope for this example.

The next thing that is different is the Maven pom. It has grown and some plugins has been added and configured. The pom now looks like this:


<?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <parent> <groupId>se.waymark</groupId> <artifactId>jsf-web-app</artifactId> <version>1.0-SNAPSHOT</version> </parent> <groupId>se.waymark</groupId> <artifactId>jsf-test</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>2.12</version> <executions> <execution> <id>integration-test</id> <phase>integration-test</phase> <goals> <goal>integration-test</goal> </goals> </execution> <execution> <id>verify</id> <phase>verify</phase> <goals> <goal>verify</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven2-plugin</artifactId> <version>1.2.2</version> <executions> <execution> <id>start-tomcat</id> <phase>pre-integration-test</phase> <goals> <goal>start</goal> </goals> </execution> <execution> <id>stop-tomcat</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> <configuration> <container> <containerId>tomcat7x</containerId> <zipUrlInstaller> <url></url> </zipUrlInstaller> <output>${}/tomcat-logs/container.log</output> <append>false</append> <log>${}/tomcat-logs/cargo.log</log> </container> <configuration> <type>standalone</type> <home>${}/tomcat-home</home> <properties> <cargo.servlet.port>8080</cargo.servlet.port> <cargo.logging>high</cargo.logging> </properties> <deployables> <deployable> <groupId>se.waymark</groupId> <artifactId>jsf-main</artifactId> <type>war</type> </deployable> </deployables> </configuration> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>se.waymark</groupId> <artifactId>jsf-main</artifactId> <version>1.0-SNAPSHOT</version> <type>war</type> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-java</artifactId> <version>1.1.1</version> <scope>test</scope> </dependency> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-junit</artifactId> <version>1.1.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.25.0</version> <scope>test</scope> </dependency> </dependencies> </project>

There are some things to notice with this pom. Lets go through them from the top.

  • Failsafe plugin – maven-failsafe-plugin
    • I bind it the to execute its integration-test goal in the integration-test phase. This will allow me to prepare a Tomcat and deploy the application in the pre-integration-test phase.
    • I also bind it to execute its verify goal in the verify phase. This will allow me to shut down Tomcat in the post-integration-test phase and check the build result. This will ensure that I never end up with a running Tomcat even after a failed build.
  • Cargo plugin – cargo-maven2-plugin
    • I bind it the to execute its start goal in the pre-integration-test phase. This will start Tomcat and deploy the web application so it is up and running when it is time for the integration test phase.
    • I also bind it to execute its stop goal in the post-integration-test phase. This will terminate Tomcat.
    • The zipUrlInstaller is used to download Tomcat if it hasn’t been downloaded yet. This means that nobody has to install Tomcat manually for this project. This is a bit fragile. The URL to the distribution zip changes when a new release of Tomcat is available. I suggest that you host the zip file at a location that you have control over and specify that location instead.

These are the most important changes.

The web application

To be able to build the system, I need to implement the web application. This is a trivial JSF application and not really important but I include it for completeness. I will therefore skip through it fast. All files needed are included, but I will not go through the details. There are a lot of other people out there who are better sent to describe a JSF application than I am.

File organisation

All files needed for this example are organised like this:

|-- jsf-main
|   |-- pom.xml
|   `-- src
|       |-- main
|       |   |-- java
|       |   |   `-- se
|       |   |       `-- waymark
|       |   |           `-- rentit
|       |   |               |-- controller
|       |   |               |   `--
|       |   |               `-- view
|       |   |                   |--
|       |   |                   |--
|       |   |                   `--
|       |   `-- webapp
|       |       |-- available.xhtml
|       |       |-- create.xhtml
|       |       |-- rent.xhtml
|       |       `-- WEB-INF
|       |           `-- web.xml
|       `-- test
|           `-- java
|               `-- se
|                   `-- waymark
|                       `-- rentit
|                           `--
|-- jsf-test
|   |-- pom.xml
|   `-- src
|       `-- test
|           |-- java
|           |   `-- se
|           |       `-- waymark
|           |           `-- rentit
|           |               |--
|           |               `-- steps
|           |                   |--
|           |                   `--
|           `-- resources
|               `-- se
|                   `-- waymark
|                       `-- rentit
|                           `-- Rent.feature
|-- pom.xml

All test files has already been presented so I will not do that again. The files needed for the web application, jsf-main, looks like this:

Parent pom

A parent pom is used to connect the two sub modules. It is defined as:


<?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <groupId>se.waymark</groupId> <artifactId>jsf-web-app</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>jsf-main</module> <module>jsf-test</module> </modules> </project>

Main application pom


<?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <parent> <groupId>se.waymark</groupId> <artifactId>jsf-web-app</artifactId> <version>1.0-SNAPSHOT</version> </parent> <groupId>se.waymark</groupId> <artifactId>jsf-main</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <build> <finalName>rentit</finalName> </build> <dependencies> <dependency> <groupId>se.waymark.educational</groupId> <artifactId>model</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-api</artifactId> <version>2.1.7</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-impl</artifactId> <version>2.1.7</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies> </project>

The final name of the war will be ‘rentit’ so I don’t have to bother with version number when I call the web application later.



package se.waymark.rentit.controller; import se.waymark.rentit.model.dao.CarDAO; import se.waymark.rentit.model.dao.InMemoryCarDAO; import se.waymark.rentit.model.entiy.Car; public class Controller { private CarDAO carDAO = new InMemoryCarDAO(); public void createCar() { Car car = new Car(); carDAO.add(car); } public void rentCar() { Car car = carDAO.findAvailableCar();; } public int getNumberOfAvailableCars() { return carDAO.getNumberOfAvailableCars(); } }

I use a controller class to connect the view and model. Following Model View Controller, MVC, is always nice.


The view wants a Java bean to read properties from. There are three of them and they are defined as below.


package se.waymark.rentit.view; import se.waymark.rentit.controller.Controller; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @ManagedBean @RequestScoped public class Available { private Controller controller = new Controller(); public int getAvailableCars() { return controller.getNumberOfAvailableCars(); } }


package se.waymark.rentit.view; import se.waymark.rentit.controller.Controller; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @ManagedBean @RequestScoped public class Create { private Controller controller = new Controller(); private int numberOfCars; public String create() { for (int i = 0; i < numberOfCars; i++) { controller.createCar(); } return "available.xhtml"; } public void setNumberOfCars(int numberOfCars) { this.numberOfCars = numberOfCars; } public int getNumberOfCars() { return numberOfCars; } }


package se.waymark.rentit.view; import se.waymark.rentit.controller.Controller; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @ManagedBean @RequestScoped public class Rent { private Controller controller = new Controller(); public String rent() { controller.rentCar(); return "available.xhtml"; } }

The user interface is built using xhtml files. The file names have to correspond to the Java beans above. They are defined as:


<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ""> <html xmlns=""> <head> <title>Available cars</title> </head> <body> Available cars <table border="1"> <tr> <th>Car class</th> <th align="right">Available cars</th> </tr> <tr> <td>Compact</td> <td align="right" id="availableCars">#{available.availableCars}</td> </tr> </table> </body> </html>


<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ""> <html xmlns="" xmlns:h=""> <head> <title>Create cars</title> </head> <body> Create rental cars <h:form id="create"> <table> <tr> <td>Number of cars:</td> <td> <h:inputText required="true" id="numberOfCars" value="#{create.numberOfCars}"></h:inputText> <h:message for="numberOfCars"></h:message> </td> </tr> <tr> <td/> <td align="right"> <h:commandButton value="Create cars" id="createButton" action="#{create.create}"></h:commandButton> </td> </tr> </table> </h:form> </body> </html>


<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ""> <html xmlns="" xmlns:h=""> <head> <title>Rent a car</title> </head> <body> Rent a car <h:form id="rent"> <h:commandButton value="Rent" id="rentButton" action="#{}"></h:commandButton> </h:form> </body> </html>

Web application

A web xml has to be defined to connect the JSF components.


<?xml version="1.0" encoding="ISO-8859-1"?> <web-app> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>faces/available.xhtml</welcome-file> </welcome-file-list> </web-app>

A test class

I wrote a simple test class to wire things together without using the web application.


package se.waymark.rentit; import org.junit.Test; import se.waymark.rentit.view.Available; import se.waymark.rentit.view.Create; import se.waymark.rentit.view.Rent; import static; import static org.junit.Assert.assertThat; public class RentCarTest { @Test public void shouldRentACar() { int initialNumberOfCars = 43; Create create = new Create(); create.setNumberOfCars(initialNumberOfCars); create.create(); int oneRentedCar = 1; int expected = initialNumberOfCars - oneRentedCar; Rent rent = new Rent();; Available available = new Available(); int actual = available.getAvailableCars(); assertThat(actual, is(expected)); } }


A simple JSF application can be added on top of the model without changing the defined behaviour. This is Behaviour Driven Development. You define the behaviour you want. Implement it. Add a GUI if it is needed but don’t change the behaviour if you don’t have to. Next exercise is to use the same behaviour but another tool for the GUI. I will use Wicket instead of JSF.

Next – A Wicket web application


  1. HI thanks a lot for your great work. I’m little bit confused with the different pom.xml. Could you please add the full path for each of them ? Thanks

    Comment by Marcus — April 3, 2014 @ 14:45

    • Hi!

      I added the missing path to the test pom. I hope this makes it clearer.


      Comment by Thomas Sundberg — April 7, 2014 @ 22:09

  2. Hi, great cuke sequence
    I am wondering about one thing in jsf-main pom


    the model code was put/copied into jsf-main, so why the dependency on the jar?

    I believe if you did a mvn install from the previous “building a model” step this jar would be in the local maven repo
    and would work, but jsf-main is not using it. However, my jsf-test wouldn’t work because its not getting to the model, so i
    included the above dependency in jsf-test pom.xml, I was running in your not-so-favorite IDE, but it wouldn’t run from
    WIn7 command line either until i added this dependency. any thoughts on what I am doing wrong?

    I also had a problem with the tomcat zip version, i had to update it to 7.0.54, seems .32 is no longer available. Is there
    a way to “generisize” this ie anything > 7.0.32 ?

    Thanks – this is definitely helping me learn cucumber!

    Comment by timr — July 4, 2014 @ 08:36

    • Hi!

      I am not entirely sure what you are doing wrong with the dependencies. I know that I build the entire project when I create the example.

      The Tomcat reference is a fragile part. The Tomcat team doesn’t keep all old versions around. If I created this example today, I would probably not use Tomcat this way. I would use a servlet container that I can obtain as a dependency from The Central Repository,


      Comment by Thomas Sundberg — July 5, 2014 @ 11:53

      • Hi,

        Sorry, my bad! It was a cut/paste error on my end, I mixed the model in with this code.
        I am now on to the Rest example and have a maven question – I will write it under the comments there

        thanks for the great tutorial/example!

        Comment by Tim — July 11, 2014 @ 19:26

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at

%d bloggers like this: