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

#Siden
https://github.com/taichi/siden
Hello Worldやったので、
http://qiita.com/masatsugumatsus/items/c07e13f81fea12fa590e

次は、RestとDBアクセス

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

```java: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を使う


```java: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
```java: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))");
		}
	}
}

```
##テスト
```groovy: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でアクセスして欲しい。