Samstag, 26. Dezember 2009

Apache CouchDB: External Process using Java and serving file

Apache CouchDB supports invoking external processes - here is a very simple example in Java, which returns an image (or another arbitrary binary file):


import java.io.FilterOutputStream;
import java.io.IOException;

import sun.misc.BASE64Encoder;

public class ExternalProcessTest {
public static void main(String[] args) throws IOException {
System.out.print("{\"code\":200,\"base64\":\"");

new BASE64Encoder().encodeBuffer(
ExternalProcessTest.class.getResourceAsStream("logo.png"),
new FilterOutputStream(System.out) {
@Override
public void write(int b) throws IOException {
if (b != '\n' && b != '\r') {
super.write(b);
}
}


});
System.out.print("\",\"headers\":{\"Content-Type\":\"image/png\"}}");
System.out.println();
System.exit(0);
}
}

This can be bundled into a runnable JAR file.
Some hints:
  • You might want to make your output return another status code in case an error ocurred
  • You might want to replace the BASE64Encoder class which is part of sun.misc with your favorite implementation.
  • Most base64 implementations add CRLF every 76 characters, which need to be stripped, because CouchDB expects to get exactly one line returned.
  • The Content-Type header should match the MIME-type of the returned file. There are also automatic ways to recognize the MIME-type of a file.
  • Don't forget the ending newline after your output.
Within your local.ini of CouchDB (to be found within etc\couchdb), you need to register your external application:

[external]
test=java -jar C:\ExternalProcessTest.jar 2>1

[httpd_db_handlers]
_test = {couch_httpd_external, handle_external_req, <<"test">>}

  • Java needs to be within your PATH variable.
  • 2>&1 suppresses error output to be logged to the CouchDB log.
  • http_db_handlers registers the handler on database level, not globally.
Additional hints:
CouchDB pipes some request data to the external process, you can receive this by reading from System.in:

String json = new BufferedReader(new InputStreamReader(System.in)).readLine();

In action:


1 Kommentar: