Categories
Uncategorized

REST Web Services in Java

I’ve been taking a look at jersey today. It’s an implementation of JSR 311, which is a proposed spec for implementing REST-like web services in Java. I started with the tutorial, which is quite frankly pretty bloody simple.

  @Path("/helloworld")
  public class HelloWorldResource {
    @GET
    @Produces("text/plain")
    public String getClichedMessage() {
      return "Hello World";
    }
  }

The javadoc for the annotations explains what they do in some more detail (Path, GET, Produces).

The tutorial also includes a method of running that standalone using the grizzly HTTP connector. But I’m a stick-in-the-mud. I want it to run under tomcat. So how do I do that? Again, it turns out to be fairly simple. Just add the jersey-supplied integration servlet to your web.xml.

  
    Dispatcher
    com.sun.jersey.spi.container.servlet.ServletContainer
    
      com.sun.jersey.config.property.packages
      net.happygiraffe.jerseytest
    
    1
  

  
    Dispatcher
    /*
  

I specified an extra parameter to say which package I want scanned for resources. Otherwise Jersey will scan everything in /WEB-INF/classes and /WEB-INF/lib by default. Anyway, this works a treat:

% curl -i http://localhost:8080/jerseytest/hello
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain
Transfer-Encoding: chunked
Date: Sat, 13 Sep 2008 20:44:41 GMT

hello world

I’m going to play with this some more. The API feels quite nice. Particularly when compared to Restlets, which I found a little bit too uniform. Mind you, the latest restlet code has its own version of JSR 311 support, so it may still be useful. It’s also actually worth checking out the JSR-311 spec, as it’s quite readable.

Categories
Uncategorized

Varnish

I listened to an interview about Varnish this morning. It was on the excellent bsdtalk podcast. Varnish is an attempt to write a high performance HTTP accelerator (reverse proxy). It grew out of frustrations with the performance of squid. Because it’s focussing on a much smaller problem space, it’s much simpler to use. Anybody who’s wrestled with squid config files before will sympathize.

It was primarily written by phk, one of the major FreeBSD contributors.

But what I found really interesting was the little nugget about the configuration of Varnish. They wanted the configuration to be a DSL, so you can easily do things like make caching decisions based on HTTP headers and URL matching and so on. But the implementation surprised me: they compile the config file to C, compile it to a shared library and then load it into the Varnish process. So it’s damned fast, as you don’t have the overhead of interpreting bytecodes like you would with embedded Ruby or Perl.

It still makes me a little nervous about the availability of compilers on a production server (it’s generally considered bad security practice). But you can always compile on an identical machine elsewhere.

Overall, it seems like an interesting tool for helping web sites to perform. I’ll try to give it some proper attention as soon as I get a chance.

Categories
Uncategorized

PUTting an URL

Today, somebody at work wanted to PUT some data to an URL. It’s part of an internal web service we use. Should be easy write. In Perl, it’s pretty trivial.

my $ua = LWP::UserAgent->new();
my $req = PUT 'http://example.com/dest', Content => $ARGV[0];
my $resp = $ua->request( $req );
die $resp->status_line, "n" unless $resp->is_success;

That takes the first command line argument and PUTs it http://example.com/dest. Pretty simple stuff. But compare this to the Java way, which is what my colleague was attempting.

public class HttpPutTest {
    public static void main(String[] args) throws IOException {
        URL dest = new URL("http://example.com/dest");
        HttpURLConnection conn = (HttpURLConnection) dest.openConnection();
        conn.setRequestMethod("PUT");
        conn.setDoOutput(true);
        conn.getOutputStream().write(args[0].getBytes());
        conn.connect();
        if (conn.getResponseCode() < 200 || conn.getResponseCode() > 299)
            throw new IOException(conn.getResponseMessage());
    }
}

Firstly, as with all Java, the sheer verbosity is staggering. But there are two things of interest to me here.

  1. The request and response are conflated into one object, an UrlConnection (or variation thereof). There’s no way to retrieve header values on the request once they’ve been set.
  2. Setting the content is done through the most contorted route. Firstly, we have to tell the connection that it’s to expect output (why? I’m doing output things below, it should work it out). Secondly, we have to fetch an OutputStream, marshal our input into bytes and then write those bytes to the stream.

It’s that OutputStream that gets me. Oh, I can see why you’d need it occasionally. But 90% of the time when you’re doing a PUT or a POST, the amount of data is tiny, and you have it all up front. So you don’t need to stream it to the server. You’re paying the price for it 100% of the time, even though it’s only needed 1% of the time, if that. Really, how hard would a setContent() method be?