Hello World for Jetty with a Gradle Build, TDD style
Java
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src
.classpath
.gitignore
.project
README.md
build.gradle

README.md

Jetty Gradle Hello World, TDD Style

I want to make a simple web app with Jetty, using Gradle as the build tool. But I'm big on Test Driven Development (TDD), so I want to do it TDD style. I'll be checking in each step to my git repository at https://github.com/ziroby/jetty-gradle-hello-world

Gradle Build File

My first task is to get a simple Gradle build file in place. Looking at http://stackoverflow.com/questions/7864521/gradle-jettyrun-how-does-this-thing-work , I get a good starter for a build.gradle file. I add boiler-plate java build/test stuff, and my build.gradle looks like:

apply plugin: 'java'
apply plugin: 'jetty'

repositories {
    mavenCentral()
}
dependencies {
    testCompile 'junit:junit:4.11'
    testCompile 'org.hamcrest:hamcrest-all:1.3'

}
test {
    exclude '**/*IntegrationTest*'
}

task integrationTest(type: Test) {
    include '**/*IntegrationTest*'
    doFirst {
        jettyRun.httpPort = 8080    // Port for test
        jettyRun.daemon = true
        jettyRun.execute()
    }
    doLast {
        jettyStop.stopPort = 8091   // Port for stop signal
        jettyStop.stopKey = 'stopKey'
        jettyStop.execute()
    }
}

I run gradle build and get success. Ready for my first test.

RESTful Server Test

I want to work from the outside in, so my first test is a test for the web service. I'm doing "Hello World", so I want a RESTful server that provides "Hello World" when I do a GET to the top level. But I want to arrange our server correctly, so I'll have a separate engine that is called by the server classes. I'll start with a test for the server.

public class HelloIntegrationTest {
    private static String HELLO_URL = "http://localhost:8080/hello";
    
    @Test
    public void testHello() throws Exception {
        Client client = Client.create();
        WebResource webResource = client.resource(HELLO_URL);
        String response = webResource.get(String.class);
        
        assertThat(response, is("Hello, World!"));
    }
}

I also pull in Jersey for the web classes.

dependencies {
    testCompile 'junit:junit:4.11'
    testCompile 'org.hamcrest:hamcrest-all:1.3'
    testCompile 'com.sun.jersey:jersey-client:1.17.1'
    testCompile 'com.sun.jersey:jersey-core:1.17.1'
}

gradle integrationTest gets a 404, so the test is written and I can now write code to make the test pass.

RESTful Server Code

I create a server class with JAX-RS annotations.

@Path("/hello")
public class HelloWebapp {
    @GET()
    public String hello() {
        return "";
    }
}

And I add dependencies to the Gradle file.

dependencies {
    ...
    compile 'com.sun.jersey:jersey-core:1.17.1'
    compile 'com.sun.jersey:jersey-server:1.17.1'
    compile 'com.sun.jersey:jersey-servlet:1.17.1'
}

The setup as is creates a web server at "http://localhost:8080//hello". I want it at root, "http://localhost:8080/hello", so I have to set the context path in the Gradle build file.

        jettyRun.contextPath = '/';

The entire build.gradle file is now:

apply plugin: 'java'
apply plugin: 'jetty'
apply plugin: 'eclipse'

repositories {
    mavenCentral()
}
dependencies {
    testCompile 'junit:junit:4.11'
    testCompile 'org.hamcrest:hamcrest-all:1.3'
    testCompile 'com.sun.jersey:jersey-client:1.17.1'
    compile 'com.sun.jersey:jersey-core:1.17.1'
    compile 'com.sun.jersey:jersey-server:1.17.1'
    compile 'com.sun.jersey:jersey-servlet:1.17.1'
}
test {
    exclude '**/*IntegrationTest*'
}

task integrationTest(type: Test) {
    include '**/*IntegrationTest*'
    doFirst {
        jettyRun.contextPath = '/';
        jettyRun.httpPort = 8080    // Port for test
        jettyRun.daemon = true
        jettyRun.execute()
    }
    doLast {
        jettyStop.stopPort = 8091   // Port for stop signal
        jettyStop.stopKey = 'stopKey'
        jettyStop.execute()
    }
}

Running this I now get an assertion failure:

java.lang.AssertionError: 
Expected: is "Hello, World!"
     but: was ""

This is the error I was looking for, so I check in the code. I'm not going to fix this yet, because I need to call my engine to get the string to return.

The Hello Service

I want to solve this with a service, so I write it like I already have the service.

@Path("/hello")
public class HelloWebapp {
    private static HelloWorldService helloWorldService = new HelloWorldService();
    
    @GET()
    public String hello() {
        return helloWorldService.sayHello();
    }
}

The HelloWorldService class is trivial:

public class HelloWorldService {
    public String sayHello() {
        return "Hello, World!";
    }
}

Now I run gradle integrationTest, and it passes, "BUILD SUCCESSFUL". I'm done.

The source code is available at https://github.com/ziroby/jetty-gradle-hello-world .