This is my notebook for the
Jetty API.
Jetty provides an Web server and javax.servlet container. It can be embedded in devices, tools, frameworks, application servers, and clusters. I find it more easier for developping and testing a new web application as it doesn't require some deployement descriptors, some configuration files, a web container, etc... like in apache tomcat. As I will show below, a whole web applications can be embedded in a single java class.
As an example, I wrote a
couchdb-like web application, named
DivanDB ('divan' is the french word for couch), using
Jetty and
Berkeleydb. The source file is available on github at:
(See also my previous post :
CouchDB for Bioinformatics: Storing SNPs - My Notebook)
The BerkeleyDB-base key/value datastore
The class
BDBStorage consists in a BerkeleyDB environment and a BerkeleyDB database. The database stores keys and the values as String.
/** a berkeley-db String/String datastore */
private static class BDBStorage
{
/** bdb environment */
private Environment environment=null;
/** string/string database */
private Database database=null;
private BDBStorage()
{
}
/** open environment & database */
private void open(File dbHome) throws DatabaseException
{
(...)
}
/** close environment & database */
private void close()
{
(...)
}
}
The web context
A servlet context is created where we put a
BDBStorage. We also tell the context about the
DivanDB servlet and the path of the application.
DivanDB app=new DivanDB();
BDBStorage storage=new BDBStorage();
ServletContextHandler context = new ServletContextHandler();
context.setAttribute(STORAGE_ATTRIBUTE, storage);
context.addServlet(new ServletHolder(app),"/*");
context.setContextPath("/divandb");
context.setResourceBase(".");
The server
The embedded server listens to the specified port. We add the context to the server, it is started and listen to the queries forever.
/* create a new server */
Server server = new Server(port);
/* context */
server.setHandler(context);
/* start server */
server.start();
/* loop forever */
server.join();
The Servlet
The servlet
DivanDB receives the POST, GET and DELETE queries just like couchdb. It decodes the JSON data using a JSON API provided in the jetty distribution. See the code for more information.
Start the server
$java -jar dist/divandb.jar
2011-06-19 18:12:16.823:INFO::jetty-8.0.0.M3
2011-06-19 18:12:16.896:INFO::Started SelectChannelConnector@0.0.0.0:8080 STARTING
Testing, using CURL
Add a single snp. Here the
id is a concatenation of the chromosome number and the genomic position:
$curl -X PUT -d '{"id":"010000011390","name":"rs75100478","avHet":0.5,"chrom":"chr1","position":11390}' http://localhost:8080/divandb/
{"ok":"true","id":["010000011390"]}
Add single snp without id (it will be generated):
$curl -X PUT -d '{"name":"rs3877545","avHet":0.375,"chrom":"chr1","position":11507}' http://localhost:8080/divandb/
{"ok":"true","id":["id972755720"]}
Add an array of SNPs:
$ curl -X PUT -d '[{"id":"010000011390","name":"rs75100478","avHet":0.5,"chrom":"chr1","position":11390},{"id":"010000011507","name":"rs3877545","avHet":0.375,"chrom":"chr1","position":11507},{"id":"010000011863","name":"rs76933399","avHet":0.46875,"chrom":"chr1","position":11863},{"id":"010000011920","name":"rs78105014","avHet":0.5,"chrom":"chr1","position":11920},{"id":"010000011959","name":"rs71234145","avHet":0.5,"chrom":"chr1","position":11959},{"id":"010000012048","name":"rs7357889","avHet":0.277778,"chrom":"chr1","position":12048},{"id":"010000012073","name":"rs76972523","avHet":0.5,"chrom":"chr1","position":12073},{"id":"010000012120","name":"rs78253371","avHet":0.5,"chrom":"chr1","position":12120},{"id":"010000012148","name":"rs78371031","avHet":0.5,"chrom":"chr1","position":12148},{"id":"010000012158","name":"rs79313092","avHet":0.5,"chrom":"chr1","position":12158},{"id":"010000012168","name":"rs74400200","avHet":0.5,"chrom":"chr1","position":12168},{"id":"010000012169","name":"rs79903148","avHet":0.375,"chrom":"chr1","position":12169},{"id":"010000012213","name":"rs79272378","avHet":0.5,"chrom":"chr1","position":12213},{"id":"010000012264","name":"rs2475482","avHet":0.444444,"chrom":"chr1","position":12264},{"id":"010000012295","name":"rs76096671","avHet":0.375,"chrom":"chr1","position":12295},{"id":"010000012295","name":"rs79461972","avHet":0.375,"chrom":"chr1","position":12295},{"id":"010000012305","name":"rs71236994","avHet":0.5,"chrom":"chr1","position":12305},{"id":"010000012332","name":"rs2981846","avHet":0.375,"chrom":"chr1","position":12332},{"id":"010000012336","name":"rs76760687","avHet":0.375,"chrom":"chr1","position":12336},{"id":"010000012355","name":"rs76588012","avHet":0.444444,"chrom":"chr1","position":12355}]' http://localhost:8080/divandb/
{"ok":"true","id":["010000011390","010000011507","010000011863","010000011920","010000011959","010000012048","010000012073","010000012120","010000012148","010000012158","010000012168","010000012169","010000012213","010000012264","010000012295","010000012295","010000012305","010000012332","010000012336","010000012355"]
Deleting a SNP:
$curl -X DELETE -d '{"id":"2065420809"}' http://localhost:8080/divandb/
{"ok":"true","id":["id972755720"]}
List all the SNPs:
$ curl http://localhost:8080/divandb/
[
{"position":11390,"id":"010000011390","_timestamp":"1308501619331","name":"rs75100478","avHet":0.5,"chrom":"chr1"},
{"position":11507,"id":"010000011507","_timestamp":"1308501619335","name":"rs3877545","avHet":0.375,"chrom":"chr1"},
{"position":11863,"id":"010000011863","_timestamp":"1308501619336","name":"rs76933399","avHet":0.46875,"chrom":"chr1"},
{"position":11920,"id":"010000011920","_timestamp":"1308501619336","name":"rs78105014","avHet":0.5,"chrom":"chr1"},
{"position":11959,"id":"010000011959","_timestamp":"1308501619337","name":"rs71234145","avHet":0.5,"chrom":"chr1"},
{"position":12048,"id":"010000012048","_timestamp":"1308501619337","name":"rs7357889","avHet":0.277778,"chrom":"chr1"},
{"position":12073,"id":"010000012073","_timestamp":"1308501619338","name":"rs76972523","avHet":0.5,"chrom":"chr1"},
{"position":12120,"id":"010000012120","_timestamp":"1308501619338","name":"rs78253371","avHet":0.5,"chrom":"chr1"},
{"position":12148,"id":"010000012148","_timestamp":"1308501619339","name":"rs78371031","avHet":0.5,"chrom":"chr1"},
{"position":12158,"id":"010000012158","_timestamp":"1308501619339","name":"rs79313092","avHet":0.5,"chrom":"chr1"},
{"position":12168,"id":"010000012168","_timestamp":"1308501619339","name":"rs74400200","avHet":0.5,"chrom":"chr1"},
{"position":12169,"id":"010000012169","_timestamp":"1308501619340","name":"rs79903148","avHet":0.375,"chrom":"chr1"},
{"position":12213,"id":"010000012213","_timestamp":"1308501619340","name":"rs79272378","avHet":0.5,"chrom":"chr1"},
{"position":12264,"id":"010000012264","_timestamp":"1308501619341","name":"rs2475482","avHet":0.444444,"chrom":"chr1"},
{"position":12295,"id":"010000012295","_timestamp":"1308501619342","name":"rs79461972","avHet":0.375,"chrom":"chr1"},
{"position":12305,"id":"010000012305","_timestamp":"1308501619344","name":"rs71236994","avHet":0.5,"chrom":"chr1"},
{"position":12332,"id":"010000012332","_timestamp":"1308501619348","name":"rs2981846","avHet":0.375,"chrom":"chr1"},
{"position":12336,"id":"010000012336","_timestamp":"1308501619348","name":"rs76760687","avHet":0.375,"chrom":"chr1"},
{"position":12355,"id":"010000012355","_timestamp":"1308501619349","name":"rs76588012","avHet":0.444444,"chrom":"chr1"}
]
List the SNPs on chr1 between 12000 and 12150:
$ curl "http://localhost:8080/divandb/?startkey=010000012000&endkey=010000012150"
[
{"position":12048,"id":"010000012048","_timestamp":"1308501619337","name":"rs7357889","avHet":0.277778,"chrom":"chr1"},
{"position":12073,"id":"010000012073","_timestamp":"1308501619338","name":"rs76972523","avHet":0.5,"chrom":"chr1"},
{"position":12120,"id":"010000012120","_timestamp":"1308501619338","name":"rs78253371","avHet":0.5,"chrom":"chr1"},
{"position":12148,"id":"010000012148","_timestamp":"1308501619339","name":"rs78371031","avHet":0.5,"chrom":"chr1"}
]
List 3 SNPs starting from index=2
$ curl "http://localhost:8080/divandb/?start=2&limit=3"
[
{"position":11507,"id":"010000011507","_timestamp":"1308501619335","name":"rs3877545","avHet":0.375,"chrom":"chr1"},{"position":11863,"id":"010000011863","_timestamp":"1308501619336","name":"rs76933399","avHet":0.46875,"chrom":"chr1"},
{"position":11920,"id":"010000011920","_timestamp":"1308501619336","name":"rs78105014","avHet":0.5,"chrom":"chr1"}
]
That's it
Pierre