2010年1月16日土曜日

Spring 3.0 REST/JAXB

Spring 3.0 の REST を試してみた。

■ やること
Spring 3.0 で REST がサポートされたというのでやってみる。ただし、余りサンプルを見かけない PUT をやってみる。あとJAXB のバインディングのやり方も確認しておきたい。

以下のような、なんちゃって仕様を実装する。

  • http://localhost:8888/hello-rest 以下にリソース Foo がある
  • Foo は id で識別され、プロパティを name 持つ。
  • たとえば、id=100 の リソース Foo をリクエストの内容で更新する操作は以下のようになる
    URLhttp://localhost:8888/hello-rest/foo/id/100
    methodPUT
    内容<foo><name>hoge</name></foo>
  • 実際にリソース更新する変わりに、操作の内容を標準出力に書き出す

■ 使うもの

  • Eclipse 3.5 Galileo + WTP + m2eclipse
  • Maven 2.2.1
  • Tomcat v6.0

■ サーバ

  • Java Project を作って、Dynamic Web Project 且つ Maven Project にする。
  • POM には 以下の依存を記述
    groupIdartifactIdversion
    org.springframeworkspring-webmvc3.0.0.RELEASE
    org.springframeworkspring-oxm3.0.0.RELEASE
    javax.servletservlet-api2.5
  • リソース Foo は以下のようなクラスで表現する(以下、パッケージはどれも springmvc.web とした)
    @XmlRootElement
    public class Foo {
       String name = "";
       public Foo() {}
       public Foo(String name) { this.name = name; }
       public void setName(String name) { this.name = name; }
       public String getName() { return name; }
    }
  • コントローラはこんな風になる。
    @Controller
    @RequestMapping("/foo")
    public class FooController {
       @RequestMapping(
             value = "/id/{fooId}", method = RequestMethod.PUT)
       public View handle(
             @RequestBody Foo foo, 
             @PathVariable int fooId) throws IOException {
          System.out.printf(
                "name of Foo(id=%d)  --> %s%n",
                fooId, foo.getName());
          return new StatusOK();
       }
    }
  • StatusOK はこんなふうにした。(合ってるかどうか、ちょい不安)
    class StatusOK implements View {
       public String getContentType() { return null; }
       public void render(Map model, HttpServletRequest request,
             HttpServletResponse response) throws Exception {
          response.setStatus(200);
       }
    }
  • これらのクラスをこんな設定ファイルで協調させる。
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-3.0.xsd">
       <context:component-scan base-package="springmvc.web" />
       <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
          <property name="messageConverters">
             <list>
                <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                   <property name="unmarshaller" ref="restXmlMarshaller" />
                </bean>
             </list>
          </property>
       </bean>
       <bean id="restXmlMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
          <property name="contextPaths">
             <list><value>springmvc.web</value></list>
          </property>
       </bean>
    </beans>
  • web.xml はほぼ自明なので省略。ただし DispatcherServlet の url-pattern は "/" とする。
  • Foo.java と同じフォルダに jaxb.index ファイルを置く。中身は単に、一言 Foo とだけ書く。
できたら、Tomcat サーバに hello-rest プロジェクトを[Add] して、エラー無くデプロイされる事を確認。

■ クライアント
クライアント用の Java プロジェクトを作って、

  • Build Path に サーバ側プロジェクトへの依存も含め、
  • POM で org.springframework の spring-webmvc の 3.0.0.RELEASE への依存を指定する
クライアントはこんなコードにする。
public class App {
   public static void main(String[] args) {
      final String uri = "http://localhost:8888/hello-rest/foo/id/100";
      RestTemplate template = new RestTemplate();
      template.put(uri, new Foo("hoge"));
   }
}
POM の<dependencies>には org.springframework の spring-webmvc の 3.0.0.RELEASE だけ指定. また、Build Path に サーバ側プロジェクトへの依存も含めておく。

実行すると、サーバ側のConsole ビューに "name of Foo(id=100) --> hoge" と 表示される。

ちなみに TCPMon で見るとこんな感じ

request
PUT /hello-rest/foo/id/100 HTTP/1.1
Content-Type: application/xml
User-Agent: Java/1.6.0_13
Host: 127.0.0.1:8888
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 83

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
   <foo>
      <name>hoge</name>
   </foo>
response
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Language: ja-JP
Content-Length: 0
Date: Thu, 14 Jan 2010 13:18:45 GMT

■ 参考サイト
この辺り

  • http://www.developer.com/java/web/article.php/10935_3854986_2/Get-RESTful-with-Spring-30.htm
  • http://grzegorzborkowski.blogspot.com/2009/03/test-drive-of-spring-30-m2-rest-support.html

0 件のコメント:

コメントを投稿