RestEasy実装サンプルのまとめ。

ここの所触ってきたRestEasy2.0.1.GAのまとめのサンプルコードになります。
使用頻度の高そうなものをサンプルコードで触れるようにしました。


このコードで下記の実装方法がだいたいわかるかと思います。
ここに載せているのはRestEasyのクラスやメソッドの使い方なので、
あとは実際にRESTの仕様にのっとった自分が必要とするRESTサービスを
作ってみるといいかと思います。


●クライアントからの各メソッドのRequestにおけるリクエストヘッダ、
 Form値、QueryString値、URLパラメータの送信方法
●サーバ側でのRequestからのレスポンスヘッダ、Form値、
 QueryString値、URLパラメータの取得方法
●サーバ側でのResponseで返すデータ部のxmljsonの元になる
 Beanの作成方法(簡単なものだけですが。。。)
●サーバ側でのResponseのステータスコードやHTTPヘッダー、
 データ部の設定方法


※レスポンスのボディ部をXMLにしたい場合は@Produces("application/json")の部分を
 @Produces("application/xml")にしてもらうとXMLでのやり取りに変わります。


pom.xml

<?xml version="1.0" encoding="UTF-16"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>sample</groupId>
  <artifactId>sample</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <!-- TODO project name  -->
  <name>quickstart</name>
  <description/>
  <dependencies>
   <dependency>
      <groupId>commons-httpclient</groupId>
      <artifactId>commons-httpclient</artifactId>
      <version>3.1</version>
  </dependency>
    <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-jaxrs</artifactId>
      <version>2.0.1.GA</version>
      <!-- filter out unwanted jars -->
      <exclusions>
        <exclusion>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
        </exclusion>
        <exclusion>
          <groupId>javax.xml.bind</groupId>
          <artifactId>jaxb-api</artifactId>
        </exclusion>
        <exclusion>
          <groupId>com.sun.xml.bind</groupId>
          <artifactId>jaxb-impl</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-jettison-provider</artifactId>
      <version>2.0.1.GA</version>
      <exclusions>
        <exclusion>
          <groupId>javax.xml.bind</groupId>
          <artifactId>jaxb-api</artifactId>
        </exclusion>
        <exclusion>
          <groupId>com.sun.xml.bind</groupId>
          <artifactId>jaxb-impl</artifactId>
        </exclusion>
        <exclusion>
          <groupId>javax.xml.stream</groupId>
          <artifactId>stax-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
  <repositories>
    <repository>
      <id>jboss</id>
      <name>jboss repo</name>
      <url>http://repository.jboss.org/nexus/content/groups/public/</url>
    </repository>
  </repositories>
  <build>
    <resources>
      <resource>
        <filtering>false</filtering>
        <directory>src/main/resources</directory>
      </resource>
      <resource>
        <filtering>false</filtering>
        <directory>src/main/java</directory>
        <includes>
          <include>**</include>
        </includes>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <filtering>false</filtering>
        <directory>src/test/java</directory>
        <includes>
          <include>**</include>
        </includes>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </testResource>
    </testResources>
    <plugins>
      <plugin>
        <inherited>true</inherited>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
          <optimize>true</optimize>
          <debug>true</debug>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <configuration>
          <downloadSources>true</downloadSources>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
  <display-name>sample</display-name>
  <context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>true</param-value>
  </context-param>
  <listener>
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
  </listener>
  <servlet>
    <servlet-name>Resteasy</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Resteasy</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

サーバ側コード

package sample.sample.resources;

import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import sample.sample.bean.ResponseBean;

/**
 * /sampleに対するリソース
 * 
 * @author bose999
 * 
 */
@Path("/sample")
public class SampleResource {

	/**
	 * コンストラクタ
	 */
	public SampleResource() {
	}

	/**
	 * /コンテキストルート/sample という形式のURLでPUTコールされた場合の処理
	 * 
	 * @param hTest01
	 *            HTTP Header h-test01
	 * @param hTest02
	 *            HTTP Header h-test02
	 * @param inputString
	 *            URL Param inputString
	 * @param qTest01
	 *            URL QueryParam(?q-test01=xx) q-test01
	 * @param qTest02
	 *            URL QueryParam(?q-test02=xx) q-test01
	 * @return Response
	 */
	@GET
	@Path("/{inputString}")
	// /コンテキスト名/sample/xxxx という形式のURLでxxxをパラメータとして定義
	@Produces("application/json")
	public Response getSample(@HeaderParam("h-test01") String hTest01,
			@HeaderParam("h-test02") String hTest02,
			@PathParam("inputString") String inputString,
			@QueryParam("q-test01") String qTest01,@QueryParam("q-test02") String qTest02) {
		
		// RestEasyにステータスコード200でResponseBeanの内容でXMLを生成して処理を返してもらう
		return makeResponse(200,hTest01 + hTest02 + inputString + qTest01+ qTest02);
	}

	/**
	 * /コンテキストルート/sample という形式のURLでPUTコールされた場合の処理
	 * 
	 * @param hTest01
	 *            HTTP Header h-test01
	 * @param hTest02
	 *            HTTP Header h-test02
	 * @param test01
	 *            Form value test01
	 * @param test02
	 *            Form value test02
	 * @param inputString
	 *            URL Param inputString
	 * @param qTest01
	 *            URL QueryParam(?q-test01=xx) q-test01
	 * @return Response
	 */
	@PUT
	@Path("/{inputString}")
	// /コンテキスト名/sample/xxxx という形式のURLでxxxをパラメータとして定義
	@Produces("application/json")
	public Response putSample(@HeaderParam("h-test01") String hTest01,
			@HeaderParam("h-test02") String hTest02,
			@FormParam("test01") String test01,
			@FormParam("test02") String test02,
			@PathParam("inputString") String inputString,
			@QueryParam("q-test01") String qTest01) {

		// RestEasyにステータスコード200でResponseBeanの内容でXMLを生成して処理を返してもらう
		return makeResponse(200,hTest01 + hTest02 + test01 + test02 + inputString + qTest01);
	}
	
	/**
	 * /コンテキストルート/sample という形式のURLでPUTコールされた場合の処理
	 * 
	 * @param hTest01
	 *            HTTP Header h-test01
	 * @param hTest02
	 *            HTTP Header h-test02
	 * @param test01
	 *            Form value test01
	 * @param test02
	 *            Form value test02
	 * @param inputString
	 *            URL Param inputString
	 * @param qTest01
	 *            URL QueryParam(?q-test01=xx) q-test01
	 * @return Response
	 */
	@POST
	@Path("/{inputString}")
	// /コンテキスト名/sample/xxxx という形式のURLでxxxをパラメータとして定義
	@Produces("application/json")
	public Response postSample(@HeaderParam("h-test01") String hTest01,
			@HeaderParam("h-test02") String hTest02,
			@FormParam("test01") String test01,
			@FormParam("test02") String test02,
			@PathParam("inputString") String inputString,
			@QueryParam("q-test01") String qTest01) {
		
		// RestEasyにステータスコード200でResponseBeanの内容でXMLを生成して処理を返してもらう
		return makeResponse(200,hTest01 + hTest02 + test01 + test02 + inputString + qTest01);
	}
	
	/**
	 * /コンテキストルート/sample という形式のURLでPUTコールされた場合の処理
	 * 
	 * @param hTest01
	 *            HTTP Header h-test01
	 * @param hTest02
	 *            HTTP Header h-test02
	 * @param inputString
	 *            URL Param inputString
	 * @param qTest01
	 *            URL QueryParam(?q-test01=xx) q-test01
	 * @return Response
	 */
	@DELETE
	@Path("/{inputString}")
	// /コンテキスト名/sample/xxxx という形式のURLでxxxをパラメータとして定義
	@Produces("application/json")
	public Response deleteSample(@HeaderParam("h-test01") String hTest01,
			@HeaderParam("h-test02") String hTest02,
			@PathParam("inputString") String inputString,
			@QueryParam("q-test01") String qTest01) {
		
		// RestEasyにステータスコード200でResponseBeanの内容でXMLを生成して処理を返してもらう
		return makeResponse(200,hTest01 + hTest02 + inputString + qTest01);
	}
	
	/**
	 * statusCodeとreturnStringの内容でレスポンスのXMLを生成する
	 * 
	 * @param statusCode int
	 * @param returnString String
	 * @return Response
	 */
	private Response makeResponse(int statusCode,String returnString){
		
		ResponseBean responseBean = new ResponseBean();
		responseBean.returnString = returnString;

		// Responseを生成するResponseBuilderをステータスコード200で生成
		ResponseBuilder responseBuilder = Response.status(200);
		
		// XMLを返す為にResponseBeanを渡す
		responseBuilder = responseBuilder.entity(responseBean);
		
		// HTTPヘッダーに値を追加
		responseBuilder.header("ORIGINAL01", "original01");
		responseBuilder.header("ORIGINAL02", "original02");
		
		// Responseを生成する
		Response response = responseBuilder.build();	
		
		return response;	
	}
}

サーバ側Bean

package sample.sample.bean;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="response")
public class ResponseBean {
	
	@XmlElement(name="return")
	public String returnString;
	
}

クライアント側コード

package sample.sample.bean.client;

import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriBuilder;

import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.spi.ResteasyProviderFactory;

import sample.sample.bean.ResponseBean;

/**
 * http://localhost:8080/sample/sampleに
 * アクセスして結果を標準出力する
 * 
 * @author bose999
 *
 */
public class SampleClient {

	/**
	 * RestEasyサーバにアクセスして結果を標準出力へ
	 * 
	 * @param args String[]
	 */
	public static void main(String[] args) {
		// RESTEasy初期化
		RegisterBuiltin.register(ResteasyProviderFactory.getInstance());

		// アクセスするURIをパラメータを含めて生成
		String inputString = "xx";
		String uri = UriBuilder.fromUri("http://localhost:8080/sample/sample")
				.path("/{inputString}").build(inputString).toString();

		ClientRequest request;
		String returnString;
		ResponseBean responseBean;
		MultivaluedMap<String, String> formMultivaluedMap;
		MultivaluedMap<String, String> headerMultivaluedMap;

		try {

			// GETでアクセスし、HTTPヘッダーとURL Queryの値を渡す
			request = new ClientRequest(uri);
			headerMultivaluedMap = request.getHeaders();
			headerMultivaluedMap.add("h-test01", "header-test01");
			headerMultivaluedMap.add("h-test02", "header-test02");
			request.queryParameter("q-test01", "query-test01");
			request.queryParameter("q-test02", "query-test02");

			// GETの戻りをStringで受けとり結果を標準出力へ
			printResponse4String(request, "GET");

			// GETの戻りをResponseBeanで受けとり結果を標準出力へ
			printResponse4ResponseBean(request, "GET");

			// PUTでアクセスし、HTTPヘッダーとForm、URL Queryの値を渡す
			request = new ClientRequest(uri);
			headerMultivaluedMap = request.getHeaders();
			headerMultivaluedMap.add("h-test01", "header-test01");
			headerMultivaluedMap.add("h-test02", "header-test02");
			formMultivaluedMap = request.getFormParameters();
			formMultivaluedMap.add("test01", "form-test01");
			formMultivaluedMap.add("test02", "fomr-test02");
			request.queryParameter("q-test01", "query-test01");

			// PUTの戻りをStringで受けとり結果を標準出力へ
			printResponse4String(request, "PUT");

			// PUTの戻りをResponseBeanで受けとり結果を標準出力へ
			printResponse4ResponseBean(request, "PUT");

			// POSTでアクセスし、HTTPヘッダーとForm、URL Queryの値を渡す
			request = new ClientRequest(uri);
			headerMultivaluedMap = request.getHeaders();
			headerMultivaluedMap.add("h-test01", "header-test01");
			headerMultivaluedMap.add("h-test02", "header-test02");
			formMultivaluedMap = request.getFormParameters();
			formMultivaluedMap.add("test01", "form-test01");
			formMultivaluedMap.add("test02", "fomr-test02");
			request.queryParameter("q-test01", "query-test01");

			// POSTの戻りをStringで受けとり結果を標準出力へ
			printResponse4String(request, "POST");

			// POSTの戻りをResponseBeanで受けとり結果を標準出力へ
			printResponse4ResponseBean(request, "POST");

			// DELETEでアクセスし、HTTPヘッダーとForm、URL Queryの値を渡す
			request = new ClientRequest(uri);
			headerMultivaluedMap = request.getHeaders();
			headerMultivaluedMap.add("h-test01", "header-test01");
			headerMultivaluedMap.add("h-test02", "header-test02");
			request.queryParameter("q-test01", "query-test01");

			// DELETEの戻りをStringで受けとり結果を標準出力へ
			printResponse4String(request, "DELETE");

			// DELETEの戻りをResponseBeanで受けとり結果を標準出力へ
			printResponse4ResponseBean(request, "DELETE");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * HTTPヘッダーの内容をすべて標準出力へ
	 * 
	 * @param responseHeaderMultivaluedMap MultivaluedMap<String, String>
	 */
	private static void printHeader(
			MultivaluedMap<String, String> responseHeaderMultivaluedMap) {
		Set<Entry<String, List<String>>> set = responseHeaderMultivaluedMap
				.entrySet();

		Iterator<Entry<String, List<String>>> itr = set.iterator();

		while (itr.hasNext()) {
			Entry<String, List<String>> enrtry = itr.next();
			String key = enrtry.getKey();
			String value = "";
			int count = 0;
			List<String> list = enrtry.getValue();
			for (String str : list) {
				if (count == 0) {
					value = value + str;
				} else {
					value = value + "," + str;
				}
				count++;
			}
			System.out.println("HTTP Header:" + key + " value:" + value);
		}
	}

	/**
	 * Stringで受けて内容を標準出力へ
	 * 
	 * @param request ClientResponse
	 * @param methodName String
	 * @throws Exception
	 */
	private static void printResponse4String(ClientRequest request,
			String methodName) throws Exception {
		ClientResponse<?> response = execHTTPMethod(request, methodName,
				String.class);
		printHeader(response.getHeaders());
		String returnString = (String) response.getEntity();
		System.out.println(methodName + " ステータスコード:" + response.getStatus());
		System.out.println(methodName + " 戻り値:" + returnString);
	}

	/**
	 * ResponseBeanに詰めて受けて内容を標準出力へ
	 * 
	 * @param request
	 * @param methodName
	 * @throws Exception
	 */
	private static void printResponse4ResponseBean(ClientRequest request,
			String methodName) throws Exception {
		ClientResponse<?> response = execHTTPMethod(request, methodName,
				ResponseBean.class);
		printHeader(response.getHeaders());
		ResponseBean responseBean = (ResponseBean) response.getEntity();
		System.out.println(methodName + " ステータスコード:" + response.getStatus());
		System.out.println(methodName + " 戻り値 return:"
				+ responseBean.returnString);
	}

	/**
	 * HTTPメソッドの種類を引数で特定しClientResponseを生成
	 * 
	 * @param request ClientRequest
	 * @param methodName String
	 * @param retrunClass Class
	 * @return ClientResponse
	 * @throws Exception
	 */
	private static ClientResponse<?> execHTTPMethod(ClientRequest request,
			String methodName, Class<?> retrunClass) throws Exception {
		ClientResponse<?> response;
		if (methodName.equals("GET")) {
			response = request.get(retrunClass);
		} else if (methodName.equals("PUT")) {
			response = request.put(retrunClass);
		} else if (methodName.equals("POST")) {
			response = request.post(retrunClass);
		} else if (methodName.equals("DELETE")) {
			response = request.delete(retrunClass);
		} else {
			response = request.get(retrunClass);
		}
		return response;
	}
}

このサンプルの標準出力の結果例

HTTP Header:Content-Type value:application/json
HTTP Header:ORIGINAL02 value:original02
HTTP Header:Transfer-Encoding value:chunked
HTTP Header:ORIGINAL01 value:original01
HTTP Header:Server value:Apache-Coyote/1.1
HTTP Header:Date value:Tue, 17 Aug 2010 15:20:55 GMT
GET ステータスコード:200
GET 戻り値:{"response":{"return":"header-test01header-test02xxquery-test01query-test02"}}
HTTP Header:Content-Type value:application/json
HTTP Header:ORIGINAL02 value:original02
HTTP Header:Transfer-Encoding value:chunked
HTTP Header:ORIGINAL01 value:original01
HTTP Header:Server value:Apache-Coyote/1.1
HTTP Header:Date value:Tue, 17 Aug 2010 15:20:55 GMT
GET ステータスコード:200
GET 戻り値 return:header-test01header-test02xxquery-test01query-test02
HTTP Header:Content-Type value:application/json
HTTP Header:ORIGINAL02 value:original02
HTTP Header:Transfer-Encoding value:chunked
HTTP Header:ORIGINAL01 value:original01
HTTP Header:Server value:Apache-Coyote/1.1
HTTP Header:Date value:Tue, 17 Aug 2010 15:20:55 GMT
PUT ステータスコード:200
PUT 戻り値:{"response":{"return":"header-test01header-test02form-test01fomr-test02xxquery-test01"}}
HTTP Header:Content-Type value:application/json
HTTP Header:ORIGINAL02 value:original02
HTTP Header:Transfer-Encoding value:chunked
HTTP Header:ORIGINAL01 value:original01
HTTP Header:Server value:Apache-Coyote/1.1
HTTP Header:Date value:Tue, 17 Aug 2010 15:20:55 GMT
PUT ステータスコード:200
PUT 戻り値 return:header-test01header-test02form-test01fomr-test02xxquery-test01
HTTP Header:Content-Type value:application/json
HTTP Header:ORIGINAL02 value:original02
HTTP Header:Transfer-Encoding value:chunked
HTTP Header:ORIGINAL01 value:original01
HTTP Header:Server value:Apache-Coyote/1.1
HTTP Header:Date value:Tue, 17 Aug 2010 15:20:55 GMT
POST ステータスコード:200
POST 戻り値:{"response":{"return":"header-test01header-test02form-test01fomr-test02xxquery-test01"}}
HTTP Header:Content-Type value:application/json
HTTP Header:ORIGINAL02 value:original02
HTTP Header:Transfer-Encoding value:chunked
HTTP Header:ORIGINAL01 value:original01
HTTP Header:Server value:Apache-Coyote/1.1
HTTP Header:Date value:Tue, 17 Aug 2010 15:20:55 GMT
POST ステータスコード:200
POST 戻り値 return:header-test01header-test02form-test01fomr-test02xxquery-test01
HTTP Header:Content-Type value:application/json
HTTP Header:ORIGINAL02 value:original02
HTTP Header:Transfer-Encoding value:chunked
HTTP Header:ORIGINAL01 value:original01
HTTP Header:Server value:Apache-Coyote/1.1
HTTP Header:Date value:Tue, 17 Aug 2010 15:20:57 GMT
DELETE ステータスコード:200
DELETE 戻り値:{"response":{"return":"header-test01header-test02xxquery-test01"}}
HTTP Header:Content-Type value:application/json
HTTP Header:ORIGINAL02 value:original02
HTTP Header:Transfer-Encoding value:chunked
HTTP Header:ORIGINAL01 value:original01
HTTP Header:Server value:Apache-Coyote/1.1
HTTP Header:Date value:Tue, 17 Aug 2010 15:20:57 GMT
DELETE ステータスコード:200
DELETE 戻り値 return:header-test01header-test02xxquery-test01