RestEasyでシリアライズ/デシリアライズでBeanをやり取りする

RestEasyから文字列を返す。その文字列はBeanをシリアライズして
Base64エンコードした文字列。


クライアントは文字列を受け取りデシリアライズしてBeanを復元。
Beanの中身で処理を行なう。


というサンプル。


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 java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import org.apache.commons.codec.binary.Base64;
import org.jboss.resteasy.annotations.GZIP;

import sample.sample.bean.ResponseBean;

/**
 * /sample/sampleSerializeに対するリソース
 * 
 * @author bose999
 * 
 */
@Path("/sampleSerialize")
public class SampleSerializeResources {
	
	/**
	 * コンストラクタ
	 */
	public SampleSerializeResources(){
	}
	
	/**
	 * GETメソッドを受けてResponseBeanを生成し
	 * シリアライズしてBase64エンコーディング文字列を返す
	 * 
	 * @param fileName String
	 * @return String
	 */
	@GET
	@GZIP
	@Produces("plain/txt")
	public String getSample(@QueryParam("fileName") String fileName){
		
		String responseBeanString = "";
		
		OutputStream outputStream = null;
		ObjectOutputStream objectOutputStream = null;
		try {
			// fileをbyte[]で取得する
			byte[] fileBinary = readBinaryFile("/data/sampleBinary/" + fileName);
			
			// シリアライズするBeanを生成し、値を詰め込む
			ResponseBean responseBean = new ResponseBean();
			responseBean.returnString = "デシリアライズされて読めてますか?";
			responseBean.fileBytes = fileBinary;
			responseBean.readTime = new Date();
			
			List<Map<Integer,Integer>> maps = new ArrayList<Map<Integer,Integer>>();
			for(int i=0;i<50;i++){
				Map<Integer,Integer> map = new HashMap<Integer,Integer>();
				map.put(i, i*10);
				maps.add(map);
			}
			responseBean.maps = maps;
			
			// ResponseBeanをシリアライズしてByteArrayOutputStreamにする
			outputStream = new ByteArrayOutputStream();
			objectOutputStream = new ObjectOutputStream(outputStream);
			objectOutputStream.writeObject(responseBean);
	       ByteArrayOutputStream byteArrayOutputStream = (ByteArrayOutputStream)outputStream;
	        
			// シリアライズ結果のbyte[]をBase64エンコーディングしてUTF-8文字列にする
			byte[] encoded = Base64.encodeBase64(byteArrayOutputStream.toByteArray());
			responseBeanString = new String(encoded, "UTF-8");
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(objectOutputStream != null){
				try {
					objectOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(outputStream != null){
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
		}
		// RestEasyにStringを返してもらう
		return responseBeanString;
	}

	
	/**
	 * フルパスのファイル名のファイルをbyte[]に変換する
	 * 
	 * @param fileName
	 *            String
	 * @return byte[]
	 * @throws IOException
	 */
	private static byte[] readBinaryFile(String fileName) throws IOException {
		File file = new File(fileName);
		int fileLength = (int) file.length();
		byte[] bytes = new byte[fileLength];
		InputStream inputStream = null;
		try {
			inputStream = new FileInputStream(file);
			inputStream.read(bytes);
		} finally {
			if (inputStream != null) {
				inputStream.close();
			}
		}
		return bytes;
	}
}

サーバ側Bean

package sample.sample.bean;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;


@SuppressWarnings("serial")
public class ResponseBean implements Serializable{
	
	public byte[] fileBytes;
	
	public Date readTime;
	
	public List<Map<Integer,Integer>> maps;
	
	public String returnString;
	
}

クライアント

package sample.sample.bean.client;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.ws.rs.core.UriBuilder;

import org.apache.commons.codec.binary.Base64;
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/sampleSerialize?fileName=xxx
 * にアクセスしてResponseBeanをデシリアライズする
 * 
 * @author bose999
 * 
 */
public class SampleDeserializeClient {

	/**
	 * EasyRestのURLにアクセスしてBase64エンコード文字列から
	 * ResponseBeanをデシリアライズする
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		// RESTEasy初期化
		RegisterBuiltin.register(ResteasyProviderFactory.getInstance());

		// アクセスするURIをパラメータを含めて生成しリクエスト
		String fileName = "xxx.png";

		// http://localhost:8080/sample/sampleSerialize?fileName=xxx.png というURIを生成
		String uri = UriBuilder
				.fromUri("http://localhost:8080/sample/sampleSerialize")
				.queryParam("fileName", fileName).build().toString();
		ClientRequest request = new ClientRequest(uri);
		request.header("Content-Encoding", "gzip");

		InputStream inputStream = null;
		ObjectInputStream objectInputStream = null;
		OutputStream outputStream = null;
		try {
			// レスポンスからファイルの文字列を取得
			ClientResponse<?> response = request.get(String.class);
			String responseBeanString = (String) response.getEntity();

			// UTF-8のBase64文字列からbyte[]を復元
			byte[] decode = Base64.decodeBase64(responseBeanString
					.getBytes("UTF-8"));

			// byte[]からResponseBeanを復元
			inputStream = new ByteArrayInputStream(decode);
			objectInputStream = new ObjectInputStream(inputStream);
			ResponseBean responseBean = (ResponseBean) objectInputStream
					.readObject();

			//結果の値を標準出力後、byte[]のフィールド値からファイルを復元
			System.out.println(responseBean.returnString);
			System.out.println(responseBean.readTime);
			System.out.println("maps value out!");
			List<Map<Integer,Integer>> maps = responseBean.maps;
			for(Map<Integer,Integer> map : maps){
				for( Entry<Integer, Integer> set : map.entrySet()){
					System.out.println("key:" + set.getKey().toString() + " value:" +set.getValue().toString());
				}
			}

			// ファイルを生成する
			File outFile = new File("/data/sampleBinary/" + "return-"
					+ fileName);
			outputStream = new FileOutputStream(outFile);
			outputStream.write(responseBean.fileBytes);

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (objectInputStream != null) {
				try {
					objectInputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}