REST client in Spring

So, how do we create a REST client in a Spring based java application. It's easy, isn't it? All you do is make an http connection and read the results. Well, not quite. In this example I use a simple call to http://realurl.org as an example.

Here is a REST client written in perl just so we have something to compare and contrast. Yeah, I know, this is a java tutorial.

use strict;
use warnings;
use LWP::UserAgent;
use URI::Escape;

my $serverUrl = "http://realurl.org/api/v1/getrealurl.php?url=";

while (my $url = <>) {
chomp($url);
my $ua=LWP::UserAgent->new;
my $result=$ua->get($serverUrl . uri_escape($url) );
print $serverUrl . uri_escape($url). "\n" , $url , "\n";
print $result->content;
print "\n--------------------------------------------------\n";
}

So what does this do? It specifies a target URL to make queries on. It reads in URLs we want to query from STDIN. One at a time it creates a LWP::UserAgent object to query that url. And then finally it prints out the response. Here is a typical run. The file "urls3" contains the line "http://t.co/UoYCkpP"

 alex@reynolds:~/projects/springroo/longurl02$ perl   testRealUrl.pl  

http://realurl.org/api/v1/getrealurl.php?url=http%3A%2F%2Ft.co%2FUoYCkpP
http://t.co/UoYCkpP
<?xml version="1.0" encoding="utf-8"?>
<root>
  <status>1</status>
  <url>
    <short>http://t.co/UoYCkpP</short>
    <real>http://www.youtube.com/watch?v=v1AJjnl2y8U</real>
  </url>
</root>

Of course this isn't very reliable as we don't check for problems, and we don't really do anything with the returned data structure.

The Java Response

So if we are doing the same thing in java we typically want the response to create some kind of object rather than just receiving text. Here I intend to use javax.xml.bind to create those objects. Looking at the response format here is what I came up with "uk.co.owal.longurl.domain.RealUrlResponse"

/**
 * 
 */
package uk.co.owal.longurl.domain;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 

/**
 * @author alex
 */

// XmLElementWrapper generates a wrapper element around XML representation
@XmlRootElement(name = "root")
public class RealUrlResponse {
    private String status;
    private RealUrl url;
    
	public RealUrlResponse() {
		super();
		this.status = "";
		this.url = null;
	}
    
	public RealUrlResponse(String status) {
		super();
		this.status = status;
	}

	// XmlElement sets the name of the entities
	@XmlElement(name="status")
	public String getStatus() {
		return status;
	}
	public void setStatus(String status) {
		this.status = status;
	}

	// XmlElement sets the name of the entities
	@XmlElement(name="url")
	public RealUrl getUrl() {
		return url;
	}

	public void setUrl(RealUrl url) {
		this.url = url;
	}
}

Note the annotations

  • @XmlRootElement(name = "root")
  • @XmlElement(name="status")
  • @XmlElement(name="url")

These are mapping the xml tags to parts of this java object.

but what about the contents of the url tag? What is the RealUrl object? That corresponds to the "child object" called "url" within the "root" tag. Here is that "uk.co.owal.longurl.domain.RealUrl"

/**
 * 
 */
package uk.co.owal.longurl.domain;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
 

/**
 * @author alex
 */


@XmlRootElement(name = "url")
public class RealUrl {
   
    private String shorturl; 
    private String longurl;

	public RealUrl() {
		super();
		this.shorturl = "";
		this.longurl = "";
	}
    
	public RealUrl(String shorturl, String longurl) {
		super();
		this.shorturl = shorturl;
		this.longurl = longurl;
	}
	
	@XmlElement(name="short")
    public String getShorturl() {
		return shorturl;
	}
	public void setShorturl(String shorturl) {
		this.shorturl = shorturl;
	}
	
	@XmlElement(name="real")
	public String getLongurl() {
		return longurl;
	}
	
	public void setLongurl(String longurl) {
		this.longurl = longurl;
	}
    
}

Again we have annotations saying which xml tags the java member variables are associated with.

The Java Request

So how do we issue a request to get such a response?



import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.Source;

...

    private UrlMap checkExternalSources(String url) {

        log.info("checkExternalSources(url) is passed " + url);

    	UrlMap urlmap = new UrlMap();

    	Source response; 
    	restTemplate = new RestTemplate();
    	try {
    		response = (Source) restTemplate.getForObject("http://realurl.org/api/v1/getrealurl.php?url={alpha}" , Source.class, url);

    		JAXBContext context = JAXBContext.newInstance(RealUrlResponse.class);
    		
    		Unmarshaller um = context.createUnmarshaller();
    		RealUrlResponse realurlresponse = (RealUrlResponse) um.unmarshal(response);

    		if( realurlresponse != null) {
    		log.info("realurl responded with status " + realurlresponse.getStatus());
    		log.info("received " + realurlresponse );
    		urlmap.setShortUrl(realurlresponse.getUrl().getShorturl());
    		urlmap.setLongUrl(realurlresponse.getUrl().getLongurl());
    		}    		
    		    		
    		
    	} catch (Exception e) {
    		log.log(Level.SEVERE, "REST call to realurl failed" + e);

    	}
       	
    	return urlmap;
    }
    

So what is happening here? We set up a RestTemplate object to actually do the network transfer. This is a Spring 3 class, somewhat like HttpTemplate. We then use JAXB to unmarshall the data returned. We basically say "The response is of type RealUrlResponse - now convert it".

And to be honest, I'm looking at the status of the response, and then ignoring it :-)

References:

  • http://blog.springsource.com/2009/03/27/rest-in-spring-3-resttemplate/
  • http://eggsylife.co.uk/2010/01/03/spring-3-restful-web-services/
  • http://www.vogella.de/articles/JAXB/article.html