---
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
<dependency>
    <groupId>com.googlecode.protobuf-java-format</groupId>
    <artifactId>protobuf-java-format</artifactId>
    <version>1.2</version>
</dependency>
```


[前回のサンプルコード](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
<
<Person><name>John Doe</name><id>1234</id><email>jdoe@example.com</email><phone><number>555-4321</number><type>HOME</type></phone></Person>
```

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
<
<Person><name>John Doe</name><id>1234</id><email>jdoe@example.com</email><phone><number>555-4321</number><type>HOME</type></phone></Person>
```


E2Eテストコードは[こんな](https://github.com/making/spring-mvc-tutorial-protobuf/blob/master/src/test/java/com/example/tutorial/AddressBookControllerTest.java)感じ。

---

こいつ、かなりやれるぞ・・・!

ProtocolBuffers RPCのサーバーサイド用途にかなり合っているのではないでしょうか。
