---
title: SpringMVC 4.1のProtocol Buffer対応が強力だった件
tags: ["Java", "Protocol Buffers", "Spring", "Spring Boot", "Spring MVC"]
categories: ["Programming", "Java", "org", "springframework", "http", "converter", "protobuf"]
date: 2014-12-14T16:08:20Z
updated: 2014-12-14T16:08:20Z
---
前回、[SpringMVC 4.1のProtocol Buffers対応](http://blog.ik.am/#/entries/287)を紹介しましたが、今イチ使いどころがわからない感じでした。
ただ、[ProtobufHttpMessageConverter](https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverter.java)のソースコードを読んでいると面白いことがわかりました。Content Negotiation対応しているのです。
つまり、デフォルトではProtobufに対応しますが、**JSONをリクエストすればJSON形式で返しますし、XMLをリクエストすればXML形式で返します**。
例えば、Protobufで用意したAPIをデバッグするのにはJSONで見た方が分かりやすいでしょうし、WebブラウザにはJSONでやり取りした方が効率が良いでしょう。テストもJSONの方がやりやすいです。
この機能を有効にするには[protobuf-java-format](https://code.google.com/p/protobuf-java-format/)を依存ライブラリに追加する必要があります。
``` xml
com.googlecode.protobuf-java-format
protobuf-java-format
1.2
```
[前回のサンプルコード](https://github.com/making/spring-mvc-tutorial-protobuf)で試してみましょう。
Controllerを再掲しておくと
``` java
@RestController
public class AddressBookController {
@RequestMapping("person")
AddressBookProtos.Person person() {
return AddressBookProtos.Person.newBuilder()
.setId(1234)
.setName("John Doe")
.setEmail("jdoe@example.com")
.addPhone(
AddressBookProtos.Person.PhoneNumber.newBuilder()
.setNumber("555-4321")
.setType(AddressBookProtos.Person.PhoneType.HOME))
.build();
}
}
```
こんなんでした。
### Protobuf
``` bash
$ curl -v http://localhost:8080/person
> GET /person HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< X-Protobuf-Schema: src/main/proto/tutorial/addressbook.proto
< X-Protobuf-Message: tutorial.Person
< Content-Type: application/x-protobuf;charset=UTF-8
< Content-Length: 45
< Date: Sun, 14 Dec 2014 15:39:05 GMT
<
John Doe� jdoe@example.com"
```
### JSON
``` bash
$ curl -v http://localhost:8080/person.json
> GET /person.json HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 14 Dec 2014 15:39:42 GMT
<
{"name": "John Doe","id": 1234,"email": "jdoe@example.com","phone": [{"number": "555-4321","type": "HOME"}]}
```
or
``` bash
$ curl -v -H "Accept: application/json" http://localhost:8080/person
> GET /person HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: application/json
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 14 Dec 2014 15:40:35 GMT
<
{"name": "John Doe","id": 1234,"email": "jdoe@example.com","phone": [{"number": "555-4321","type": "HOME"}]}
```
### XML
``` bash
$ curl -v http://localhost:8080/person.xml
> GET /person.xml HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/xml;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 14 Dec 2014 15:41:48 GMT
<
John Doe1234jdoe@example.com555-4321HOME
```
or
``` bash
$ curl -v -H "Accept: application/xml" http://localhost:8080/person
> GET /person HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: application/xml
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/xml;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 14 Dec 2014 15:42:26 GMT
<
John Doe1234jdoe@example.com555-4321HOME
```
E2Eテストコードは[こんな](https://github.com/making/spring-mvc-tutorial-protobuf/blob/master/src/test/java/com/example/tutorial/AddressBookControllerTest.java)感じ。
---
こいつ、かなりやれるぞ・・・!
ProtocolBuffers RPCのサーバーサイド用途にかなり合っているのではないでしょうか。