覚えておくといつか必ず役に立つ。Javaで簡単Web API作成。- JAX-RS -

Javaアーキテクチャシリーズ。Web(Http)のAPIを簡単にJavaで作ることができる、JAX-RSという仕様があるのをご存知でしょうか。
PojoでServletやStrutsのActionに相当するレイヤーを作ることができるため、単体テストを簡単に作ることができ、ポータビリティーに優れるクラスを作成することができます。

JavaでWebアプリケーションを作るときはプレゼンテーション層の選択肢の一つとしてJAX-RSを検討されることをおすすめします。

ここではJAX-RSの実装として、参照実装であるJerseyのセットアップ方法とサンプルコードをお見せします。

JerseyのサンプルはWebを探すといくつか出てくるものの、バージョンが混在しているためか、なかなかそのまま作って動くものはありません。いつかあなたがJAX-RSでWebアプリケーションを作成するときのため、このページを覚えておくことをおすすめします。

# 環境
* [Tomcat](http://tomcat.apache.org/) 8.0 たぶん、サンプルは他のバージョンでも動きます。
* [Jersey](https://jersey.java.net/) 2.9
* [JSONIC](http://jsonic.sourceforge.jp/) 1.3
JSONICはオブジェクトをJSONに変換するために使います。

# サンプルコード
サンプルコードは[こちら](https://github.com/ukiuni/JAXRSInspect)です。
Eclipseのプロジェクトになっているので、importして、Run on Serverで動きます。
確認してはいませんが、J2EE Webプロファイルのものであれば、いろんな環境で動くと思います。お試しあれ。

# セットアップ
Jerseyの[ダウンロードページ](https://jersey.java.net/download.html)からJersey JAX-RS 2.0 RI bundle をダウンロードして下さい。zipの中身のjarファイルを軒並みWEB-INF/libに突っ込みます。
JSONICもダウンロードしてWEB-INF/libに突っ込んでください。
あとは、web.xmlを書くだけでセットアップ完了です。

```xml:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">
	<servlet>
		<servlet-name>jersey-serlvet</servlet-name>
		<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
		<init-param>
			<param-name>jersey.config.server.provider.packages</param-name>
			<param-value>org.ukiuni.inspect.jaxrs</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>jersey-serlvet</servlet-name>
		<url-pattern>/api/*</url-pattern>
	</servlet-mapping>
</web-app>  
```
変更するべきなのは、org.ukiuni.inspect.jaxrsという、パッケージ名をあなたのプロジェクトで使うパッケージ名に変更することくらいです。JAX-RSのエンドポイント名は/api/*のまま使用することをおすすめします。

# サンプルコードの解説
Web APIのエンドポイントを作ります。アノテーションで装飾されたPojoです。

```java:IndexAction.java
package org.ukiuni.inspect.jaxrs;

import ・・・省略

@Path("/")
public class IndexAction {
	@GET
	@Path("/loadMessages")
	@Produces(MediaType.APPLICATION_JSON)
	public List<MyData> loadList() {
		List<MyData> datas = new ArrayList<MyData>();
		datas.add(new MyData(1, "test1"));
		datas.add(new MyData(2, "test2"));
		datas.add(new MyData(3, "test3"));
		return datas;
	}

	@POST
	@Path("/putMessage")
	@Produces(MediaType.APPLICATION_JSON)
	public void put(@FormParam("message") String message) {
		MyData myData = new MyData();
		myData.setMessage(message);
		System.out.println("message = " + message);
		// put Message
	}
}
```
重要なのはクラスやメソッドに付いているアノテーションです。このアノテーションにより外部からメソッドにアクセスできるようになっています。
読めば大体わかりますよね。

もう一つ重要なのは、戻り値をJSONに変換するクラス、Providerです。
ここでは、JSONを返却するカスタムProviderを作成しています。

```java:JSONProvider.java
package org.ukiuni.inspect.jaxrs;

import ・・・省略

@Provider()
@Produces(MediaType.APPLICATION_JSON)
public class JSONProvider implements MessageBodyWriter {
	@Override
	public long getSize(Object arg0, Class arg1, Type arg2, Annotation[] arg3, MediaType arg4) {
		try {
			return JSON.encode(arg0).getBytes("UTF-8").length;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public boolean isWriteable(Class arg0, Type arg1, Annotation[] arg2, MediaType arg3) {
		return true;
	}

	@Override
	public void writeTo(Object arg0, Class arg1, Type arg2, Annotation[] arg3, MediaType arg4, MultivaluedMap arg5, OutputStream arg6) throws IOException, WebApplicationException {
		JSON.encode(arg0, arg6);
	}
}
```
MessageBodyWriterを実装したクラスを作成します。クラスのアノテーションをお忘れなく。

これだけで、Web API作成完了です。簡単。

# JAX-RSのアーキテクチャ上の位置づけ
JAX-RSはもともとRESTfulなWebアプリケーションを作るための仕様です。なので、私のオススメとしては、クライアント層はHTMLとJavaScriptだけで作成し、サーバサイドはすべてRESTのAPIとしてJAX-RSで作ることです。JSPなんてHTMLとそうでないのがグチャグチャになるし、JSFなんて(ry

アーキテクチャの検討は[こちら](http://qiita.com/ukiuni@github/items/b9d18b44570ece0e3933)を随時更新しています。ご確認あれ。