Edited at

SidenでRestサービスとDBアクセス

More than 3 years have passed since last update.


Siden

https://github.com/taichi/siden

Hello Worldやったので、

http://qiita.com/masatsugumatsus/items/c07e13f81fea12fa590e

次は、RestとDBアクセス


Entity

Lombok使えって話しだが。。。


Book.java

import java.io.Serializable;

public class Book implements Serializable{

/**
*
*/

private static final long serialVersionUID = 6484020759599047569L;

private String isbn;
private String name;

public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}



Resouceクラス

bodyの取り出し方が分かりません。。。

JsonライブラリはなれているからGsonを使う


BookResource.java


import java.io.IOException;
import java.nio.ByteBuffer;

import ninja.siden.App;
import ninja.siden.Renderer;
import ninja.siden.Request;

import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.Handle;
import org.xnio.channels.StreamSourceChannel;

import com.google.gson.Gson;

public class BookResource {

private App app;
private DBI dbi;
private Gson gson = new Gson();

public BookResource(App app, DBI dbi) {
this.app = app;
this.dbi = dbi;
}

@Override
public void defineRoutes() {

app.post(
"/books",
(req, res) -> {
String body = body(req);
Book book = gson.fromJson(body, Book.class);;
try (Handle h = dbi.open()) {
h.execute(
               "MERGE INTO book(isbn, name) VALUES(?, ?)",
              book.getIsbn(),
              book.getName());
}
return book;
}).render(Renderer.of(gson::toJson))
.type("application/json");;

app.get("/books/:isbn",
(req, res) -> {
return req.params("isbn")
.map(isbn -> {
Book b = null;
try (Handle h = dbi.open()) {
b = h.createQuery( "SELECT isbn,name "
+"FROM book WHERE isbn=:isbn")
.bind("isbn", isbn).map(Book.class)
.first();

}
return b;
}).orElseThrow(ResouceNotFoundException::new);
}).render(Renderer.of(gson::toJson))
.type("application/json");
}

private String body(Request req) {
int size = (int) req.raw().getRequestContentLength();
ByteBuffer buff = ByteBuffer.allocate(size);
try (StreamSourceChannel reqChannel = req.raw().getRequestChannel()) {
reqChannel.read(buff);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}

return new String(buff.array());

}
}



main


Application.java

import javax.sql.DataSource;

import ninja.siden.App;

import org.h2.jdbcx.JdbcConnectionPool;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.Handle;

public class Application {
public static void main(String[] args) {
DataSource ds = JdbcConnectionPool.create("jdbc:h2:mem:test",
"username",
"password");
DBI dbi = new DBI(ds);

init(dbi);

App app = new App();
new BookResource(app,dbi).defineRoutes();

app.listen();
}

private static void init(DBI dbi) {
try(Handle h = dbi.open()){
h.execute("create table book(isbn varchar(11) primary key, name varchar(100))");
}
}
}



テスト


BookResourceSpec.groovy


package com.sidensample.mm;

import javax.sql.DataSource;

import org.h2.jdbcx.JdbcConnectionPool;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.Handle;

import groovyx.net.http.RESTClient
import ninja.siden.App
import spock.lang.Ignore;
import spock.lang.Shared
import spock.lang.Specification

class BookResourceSpec extends Specification {

@Shared stop
def endpoint = new RESTClient( 'http://localhost:8080/' )

def setupSpec(){
DataSource ds = JdbcConnectionPool.create("jdbc:h2:mem:test",
"username",
"password");
DBI dbi = new DBI(ds);
Handle h = dbi.open();
h.execute("create table book(isbn varchar(11) primary key, name varchar(100))");
h.execute("insert into book(isbn, name) values (?, ?)", "1234", "ほんの名前");

h.close();

def app = new App()

new BookResource(app,dbi).defineRoutes()
stop = app.listen()
}

def "postのテスト"(){
when:

def resp=endpoint.post([ path: 'books',
body:[isbn:"1234",name:"abcd"],
requestContentType:"application/json"
])

def resp2=endpoint.get([ path: 'books/1234'])

then:
with(resp) {
status == 200
data.isbn == "1234"
data.name == "abcd"
}
with(resp2) {
status == 200
data.isbn == "1234"
data.name == "abcd"
}
}

def cleanupSpec(){
stop.stop()
}
}


Dropwizardよりも簡単なのは凄いな。microserviceにはいけるんではないか。


要望

・管理用の別ポート設定(多分できるけど、もう少し簡単に。。。)

・body部取得の方法(自信ない。。。)

・静的コンテンツをClasspathResourceでアクセスして欲しい。