JBossのRESTEasyにおけるMultipart Requestの文字化け対策

仕事で若干困ったのと、文字化け系の現象なのだが、同内容の対応についての日本語ページがまったく引っ掛からなかったので、メモしておく.

### 背景

やろうとしていたことは、↓.

+ `multipart/form-data`でJAX-RS(JBoss EAP 6.2, RestEASY)にファイルをUpload.
+ フォームデータには日本語を許可.

コードのイメージは下記な感じだ.

```java:FileResource.java
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;

@Path("/file")
public class FileResource {

	@POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
	public Response create(@MultipartForm UploadData uploadData){
		
		String fileName = uploadData.getFileName(); // ★ こいつが文字化!
		// 色々処理...
		return Response.ok().build();
	}
}
```

```java:UploadData.java
public class UploadData implements Serializable{
	private String fileName;
	private byte[] fileBody;
	public String getFileName() {
		return fileName;
	}
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	public byte[] getFileBody() {
		return fileBody;
	}
	public void setFileBody(byte[] fileBody) {
		this.fileBody = fileBody;
	}
	
	
}	
```

RESTEasyの拡張アノテーション`@MultipartForm`でデータの取得をしようとするも、日本語を含む項目が悉く文字化けする.

## 原因

仕方なく、multipart関連のProvider実装(org.jboss.resteasy:resteasy-multipart-provider:2.3.6-final)のソースを読んでみたところ、`org.jboss.resteasy.plugins.providers.multipart.InputPart` のJavadocに下記が書いてあった.

```java
	/**
	 * If there is a content-type header without a charset parameter, charset=US-ASCII
	 * is assumed.
	 * <p>
    * This can be overwritten by setting a different String value in
    * {@link org.jboss.resteasy.spi.HttpRequest#setAttribute(String, Object)}
    * with this ("resteasy.provider.multipart.inputpart.defaultCharset")
    * String as key. It should be done in a
    * {@link org.jboss.resteasy.spi.interception.PreProcessInterceptor}.
    * </p>
	 */
	static final String DEFAULT_CHARSET_PROPERTY = "resteasy.provider.multipart.inputpart.defaultCharset";
```

要は、「multipartの各partについて、content-type=○○; charset=... のようなヘッダが無い場合, ProviderはUS-ASCIIで文字コード変換するよ」という内容だ.

### 対応方法
JavaDocにも書いてある通り、`org.jboss.resteasy.spi.HttpRequest#setAttribute`に `"resteasy.provider.multipart.inputpart.defaultCharset"`をセットする方法でやってみたところ、無事解決(なお、後からこのキー名でググってみたら、JavaDocだけでなく、RESTEasy本家のドキュメントにも記載がありました...).

```java:ContentTypeSetterPreProcessorInterceptor.java
import org.jboss.resteasy.plugins.providers.multipart.InputPart;

@Provider
@ServerInterceptor
public class ContentTypeSetterPreProcessorInterceptor implements
		PreProcessInterceptor {

	public ServerResponse preProcess(HttpRequest request,
			ResourceMethod method) throws Failure, WebApplicationException {
		request.setAttribute(InputPart.DEFAULT_CHARSET_PROPERTY, "UTF-8");
		return null;
	}

}
```

`PreProcessInterceptor`は http://docs.jboss.org/resteasy/docs/2.3.6.Final/userguide/html_single/index.html#PreProcessInterceptors にもある通り、RESTEasyのリクエスト時に `HttpRequest`への拡張ポイントとして利用できる. `@Provider`が付与されていれば、勝手にJBossがInterceptorとして登録してくれるため、特に設定ファイル等の記載は不要. 

### 参考リンク
+ RESTEasyのドキュメント http://docs.jboss.org/resteasy/docs/2.3.6.Final/userguide/html_single/index.html#multipart_overwrite_default_charset
+ 関連JavaDoc
https://docs.jboss.org/resteasy/docs/2.3.6.Final/javadocs/org/jboss/resteasy/plugins/providers/multipart/InputPart.html