JAX-RSを使用してRESTfulサービス開発

先のエントリーの「JavaによるRESTfulシステム構築」を読んだので本の中のサンプルをベースに簡単に実装方法を紹介。

1. jerseyの取得

JAX-RSの実装として、Jerseyを使用します。
http://jersey.java.net/
Downloadページでは、Mavenを使用した説明が書いていますが、
zipファイルを取得するリンクがあるのでそちらからダウンロードします。

  • jersey-archive-1.7.zip

展開すると以下のファイルが含まれています

  • asm-3.1jar
  • jackson-core-asl-1.7.1.jar
  • jackson-jaxrs-1.7.1.jar
  • jackson-mapper-asl-1.7.1.jar
  • jackson-xc-1.7.1.jar
  • jersey-client-1.7.jar
  • jersey-core-1.7.jar
  • jersey-json-1.7.jar
  • jersey-server-1.7.jar
  • jettison-1.1.jar
  • jsr311-api-1.1.1.jar

2.jerseyの組み込み

Tomcatを使用してみます。開発環境は、Eclipseを使用します。
「Dynamic Web Project」を作成します。
上記のファイルを、WEB-INF/libに格納し、ビルドパスにも追加します。

3. web.xmlの設定

web.xmlに、JerseyのServletContainerを登録します。

<servlet>
  <servlet-name>Jersey Web Application</servlet-name>
  <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>Jersey Web Application</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

4. モデルクラスの作成

Userというbeanモデルクラスを作成します。これを扱うサービスとします。

@XmlRootElement(name="user")
public class User {
    private int id;
    private String name;
    private int age;
 
    @XmlElement(name="id")
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
     
    @XmlElement(name="name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
     
    @XmlElement(name="age")
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

5. Serviceクラスを作成

UserServiceというクラスを作成し、Userの取得、作成、更新、削除を
出来るようにしてみます。
まずは、クラス定義とデータ操作メソッド。
@Pathで、このクラスが受け付けるパスを設定します。
usersは、DBの代わりです。
findUser, deleteUserで取得更新機能を提供します。

@Path("/user")
public class UserService {
 
    private static Map<Integer, User> users = new ConcurrentHashMap<Integer, User>();
 
    private User findUser(int id) {
        User user = users.get(id);
        return user;
    }
     
    private void deleteUser(int id) {   
        if (users.get(id) != null) {
            users.remove(id);
        }       
    }


まずは、取得。メソッドはGETです。
@Pathと@PathParamでパラメータを引数に取れます。
また、@ProducesでレスポンスのContent-Typeを指定すると
JAX-RSが勝手にreturnしたUserをJAXBで、XMLにして返却してくれます。

@GET
@Path("{id}")
@Produces("application/xml")
public User getUser(@PathParam("id") int id) {
 
    User user = findUser(id);
    if (user == null) {
        throw new WebApplicationException(Response.Status.NOT_FOUND);
    }
    return user;
}
GET /RestSample/user/23 HTTP/1.1
Host: localhost:8080
 
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Sun, 22 May 2011 03:17:03 GMT
 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
<age>34</age>
<id>23</id>
<name>Koshi Inaba</name>
</user>


次は登録。メソッドはPOSTです。
@Consumesでリクエストの形式を指定します。
そうすると、メソッドの引数にUserを指定すると、こちらも
リクエストを解析し、userに設定してくれます。

@POST
@Consumes("application/xml")
@Produces("application/xml")
public User create(User user) {
    users.put(user.getId(), user);
    return user;
}
POST /RestSample/user/ HTTP/1.1
Content-Type: application/xml
Host: localhost:8080
Content-Length: 109
 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><user><age>34</age><id>34</id><name>TAK MATSUMOTO</name></user>
 
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/xml
Content-Length: 109
Date: Sun, 22 May 2011 03:16:54 GMT
 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><user><age>34</age><id>34</id><name>TAK MATSUMOTO</name></user>


次は更新。メソッドはPUTです。
アノテーションとメソッド引数は取得と登録の組み合わせな感じ。

@PUT
@Path("{id}")
@Consumes("application/xml")
public Response update(@PathParam("id") int id, User update) {
     
    User current = findUser(id);
    if (current == null) {
        throw new WebApplicationException(Response.Status.NOT_FOUND);
    }
    current.setName(update.getName());
    current.setAge(update.getAge());
     
    return Response.ok().build();
}
PUT /RestSample/user/23 HTTP/1.1
Content-Type: application/xml
Host: localhost:8080
Content-Length: 115
 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><user><age>34</age><id>23</id><name>mabushii_sign</name></user>
 
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Sun, 22 May 2011 02:58:18 GMT


最後に削除。メソッドはDELETEです。

@DELETE
@Path("{id}")
public Response delete(@PathParam("id") int id) {
     
    deleteUser(id); 
    return Response.ok().build();
}
DELETE /RestSample/user/23 HTTP/1.1
Host: localhost:8080
 
 
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Sun, 22 May 2011 06:20:19 GMT

まとめ

このように、簡単にRESTサービスを組むことが出来ます。
また、application/xmlをapplication/jsonにすればJSONにすることも出来ます。
もちろん、他のHTTPヘッダーやCookieなども簡単に設定することが出来ます。

JavaによるRESTfulシステム構築

JavaによるRESTfulシステム構築