Showing posts with label Jetty. Show all posts
Showing posts with label Jetty. Show all posts

Friday, December 17, 2010

A Mock Service with Groovy and Jetty

I recently needed to do some testing on a project that integrated with a Web service supported by another team of developers. After I completed my development work, I wanted to do some quick integration testing but I was forced to wait on the completion of the Web services. I was pretty confident that my code changes would work, but I really needed that "live" interactivity to know for sure.

In order to not be caught in this predicament again, I decided to create a simple mock service using Groovy, Jetty and some static XML files. Here is the result using an example domain model and sample data:

I put together a Groovy script to create an instance of a Jetty server. This is very similar to the example that can be found on the Groovy Web site (wink, wink).

import org.mortbay.jetty.Server
import org.mortbay.jetty.servlet.*
import groovy.servlet.*

@Grab(group = 'org.mortbay.jetty', module = 'jetty-embedded', version = '6.1.0')
def runServer = {
    def server = new Server(8181)
    def context = new Context(server, "/", Context.SESSIONS);
    
    context.resourceBase = "."
    context.addServlet(new ServletHolder(new TemplateServlet()), "*.html")
    context.addServlet(new ServletHolder(new DefaultServlet()), "*.xml")

    server.start()
}

runServer()

First, we import what we need from Jetty and here I am using @Grab to resolve our Jetty dependency.

Next, runServer is defined to do all of our work. Within runServer, we define a new Jetty Server and use it to create a new Jetty Context. I then set the context's resourceBase to "." which is the directory where the above Groovy file, mockService.groovy, is located.

Now, we need to handle requests to our server. Instead of using a standard Web descriptor, web.xml, file we can write a few line of code to add a new Groovy TemplateServlet mapped to handle the *.html request pattern and a new Jetty DefaultServlet mapped to handle the *.xml request pattern.

The Jetty DefaultServlet will handle resolving our static, test XML files.

The TemplateServlet will handle resolving and running our HTML files and it will allow us to be able to create dynamic Groovy templates like the following:

<html>
    <body>
        

File List

<% def f = new File(".") if(f.isDirectory()) { f.listFiles([accept:{file->file ==~ /.*?\.xml/}] as FileFilter).toList()*.name.each { %> ${it} <% } } %> </body> </html>


What is great about the TemplateServlet is that the above, fileList.html, contains Groovy that will be executed when the file is requested. This executed code will find all .xml files located in the current directory and display HTML links to each test XML file. For example, I have these two static, test files:

12345.xml

<?xml version="1.0" encoding="UTF-8"?>
<account>
    <id>12345</id>
    <name>Acount 12345</name>
    <address>
        <street1>123 Test St</street1>
        <city>City</city>
        <state>State</state>
        <postalcode>33333</postalcode>
    </address>
</account>

54321.xml

<?xml version="1.0" encoding="UTF-8"?>
<account>
    <id>54321</id>
    <name>Acount 54321</name>
    <address>
        <street1>123 Test St</street1>
        <city>City</city>
        <state>State</state>
    <postalcode>33333</postalcode>
    </address>
</account>


The fileList.html request will render something like:

File List


12345.xml
54321.xml

All we need to do to get started is open a command prompt, navigate to my development directory where the mockService.groovy file is located and run:

> groovy mockService.groovy

Now, my application can be configured to point to this local service. In this example, when I want to do a GET request for 'Account 12345', the application can make a call to http://localhost:8181/12345.xml. We can follow that pattern and request 'Account 54321' by calling http://localhost:8181/54321.xml or any other xxxxx.xml file I place in my development directory. I am now able to run simple integration tests with my application while the other team works to complete the final service.

To really understand the simplicity that is involved, here is a quick view of my development directory:

/mockService
- 12345.xml
- 54321.xml
- fileList.html
- mockService.groovy

Nothing too magical going on here but for me it is just another way to bring Groovy into the work environment to get things done.