This code should work against the Limpopo webservice currently deployed at http://wwwdev.ebi.ac.uk/fgpt/limpopo. This is work in progress, and may be subject to change without notice - use at your own risk!
The following code has two required dependencies: the Apache httpclient library for sending GET and POST requests, and the Codehaus Jackson library for JSON processing. Otherwise, this code should run out of the box.
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A simple client that demonstrates some features of the REST API behind the Limpopo web service.
*
* Runs from the command line, and takes a single argument - the accession to retrieve from ArrayExpress.
*
* @author Tony Burdett
* @date 12/07/11
*/
public class LimpopoRESTClient {
private HttpClient client = new HttpClient();
public static void main(String[] args) {
try {
LimpopoRESTClient client = new LimpopoRESTClient();
client.runDemo(args[0]);
}
catch (Exception e) {
System.err.print("Application failed: " + e.getMessage());
System.exit(1);
}
}
public void runDemo(String accession) {
// pass accession to the service to fetch json
String getJson = fetchMAGETAB(accession);
System.out.println("We sent a GET request to the server for " + accession + " and got the following response:");
System.out.println(getJson);
System.out.println("\n\n\n============================\n\n\n");
// now, just to prove we can roundtrip, parse the json into a simple magetab representation (two 2D String arrays)
MAGETABSpreadsheet dataFromServer = parseLimpopoJSON(getJson);
// now, post these 2D string arrays to the server and collect any error items
String postJson = sendMAGETAB(dataFromServer.getIdf(), dataFromServer.getSdrf());
System.out.println("We POSTed IDF and SDRF json objects to the server, and got the following response:");
System.out.println(postJson);
System.out.println("\n\n\n============================\n\n\n");
// now, extract error items from the resulting JSON
List<Map<String, Object>> errors = parseErrorItems(postJson);
System.out.println("Our POST operation has returned " + errors.size() + " error items, these follow:");
for (Map<String, Object> error : errors) {
System.out.println("\t" +
error.get("code") + ":\t" +
error.get("comment") + "\t[line " +
error.get("line") + ", column" +
error.get("column") + "]");
}
}
public String fetchMAGETAB(String accession) {
// send a request to limpopo
String getURL = "http://wwwdev.ebi.ac.uk/fgpt/limpopo/api/accessions/" + accession;
GetMethod get = new GetMethod(getURL);
get.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler(3, false));
// execute the method method to retrieve json for 'accession'
return executeGet(get);
}
public String sendMAGETAB(String[][] idf, String[][] sdrf) {
// create post method for sending json back
String postURL = "http://wwwdev.ebi.ac.uk/fgpt/limpopo/api/magetab";
PostMethod post = new PostMethod(postURL);
return executePost(post, idf, sdrf);
}
public String convert2DStringArrayToJSON(String[][] in) {
try {
JsonFactory jsonFactory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(jsonFactory);
StringWriter out = new StringWriter();
JsonGenerator jg = jsonFactory.createJsonGenerator(out);
mapper.writeValue(jg, in);
return out.toString();
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
public MAGETABSpreadsheet parseLimpopoJSON(String json) {
try {
// parse json
JsonFactory jsonFactory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(jsonFactory);
TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() {
};
HashMap<String, Object> requestResults = new HashMap<String, Object>();
requestResults = mapper.readValue(json, typeRef);
List<List<String>> idfObject = (List<List<String>>) requestResults.get("idf");
List<List<String>> sdrfObject = (List<List<String>>) requestResults.get("sdrf");
String[][] idf = new String[idfObject.size()][];
int i = 0;
for (List<String> row : idfObject) {
String[] rowArr = new String[row.size()];
idf[i] = row.toArray(rowArr);
i++;
}
String[][] sdrf = new String[sdrfObject.size()][];
int j = 0;
for (List<String> row : sdrfObject) {
String[] rowArr = new String[row.size()];
sdrf[j] = row.toArray(rowArr);
j++;
}
return new MAGETABSpreadsheet(idf, sdrf);
}
catch (JsonMappingException e) {
throw new RuntimeException(e);
}
catch (JsonParseException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
public List<Map<String, Object>> parseErrorItems(String json) {
try {
// parse json
JsonFactory jsonFactory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(jsonFactory);
TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() {
};
HashMap<String, Object> requestResults = new HashMap<String, Object>();
requestResults = mapper.readValue(json, typeRef);
return (List<Map<String, Object>>) requestResults.get("errors");
}
catch (JsonMappingException e) {
throw new RuntimeException(e);
}
catch (JsonParseException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
public String executeGet(GetMethod get) {
try {
// Execute the method.
int statusCode = client.executeMethod(get);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + get.getStatusLine());
}
else {
System.out.println("Sent GET request to " + get.getURI() + ", response code " + statusCode);
}
// Read the response body.
return parseResponse(get);
}
catch (HttpException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
finally {
// Release the connection.
get.releaseConnection();
}
}
public String executePost(PostMethod post, String[][] idf, String[][] sdrf) {
// create json objects from the IDF and SDRF parts of the spreadsheet
String idfJson = convert2DStringArrayToJSON(idf);
String sdrfJson = convert2DStringArrayToJSON(sdrf);
post.addParameter("idf", idfJson);
post.addParameter("sdrf", sdrfJson);
// bounce back to the magetab parsing hook
try {
client.executeMethod(post);
if (post.getStatusCode() != HttpStatus.SC_OK) {
System.err.println("Method failed: " + post.getStatusLine());
}
else {
System.out.println("Sent POST request to " + post.getURI());
System.out.println("The following parameters were posted along with this request:");
System.out.println("IDF:\n" + idfJson);
System.out.println("SDRF:\n" + sdrfJson);
}
return parseResponse(post);
}
catch (HttpException e) {
throw new RuntimeException("Fatal protocol violation: " + e.getMessage(), e);
}
catch (IOException e) {
throw new RuntimeException("Fatal transport error: " + e.getMessage(), e);
}
finally {
// Release the connection.
post.releaseConnection();
}
}
public String parseResponse(HttpMethodBase method) {
try {
String charset = method.getResponseCharSet();
for (Header header : method.getResponseHeaders()) {
if (header.getName().contains("Content-Type")) {
// check we have a json response
if (header.getValue().contains("application/json")) {
// all ok, method response body and convert to json
System.out
.println("This request generated a valid response with application/json response type");
byte[] responseBody = method.getResponseBody();
return new String(responseBody, charset);
}
else {
throw new RuntimeException("Unexpected response type: should be application/json");
}
}
}
throw new RuntimeException("No Content-Type header found");
}
catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
catch (URIException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
public class MAGETABSpreadsheet {
private String[][] idf;
private String[][] sdrf;
public MAGETABSpreadsheet(String[][] idf, String[][] sdrf) {
this.idf = idf;
this.sdrf = sdrf;
}
public String[][] getIdf() {
return idf;
}
public String[][] getSdrf() {
return sdrf;
}
}
}