X

An Oracle blog about WebLogic Channel

[連載] WebLogic Server 12cでJava EE 6を動かしてみよう!(6) JAX-RS 第1回

Nobuhiko Sekiya
Sales Consultant
実践! Java EE 6 ロゴ

本連載は、サンプル・アプリケーションの開発を通じてJava Platform, Enterprise Edition 6 (Java EE
6)の仕様とその魅力をお伝えすることを目的としています。今回から2回にわたって、Java API for

RESTful Webサービス
(JAX-RS)をとりあげます。Restful
Webサービスは従来のWebサービスよりも軽量でスケラーブルであり、大量アクセスのWebサービスに向きます。また、クライアント側の使用する機能が
基本的にHTTPだけでよいことから、様々なデバイスからのアクセスが可能です。その他、管理系ツールの操作インターフェースとしても応用されています。
JAX-RSはこういったRestful
WebサービスのJavaでの標準APIをJavaEE環境で実現したものです。今回はJAX-RSによるRestful
WebサービスのサンプルアプリケーションをWebLogic12cとOEPEを使って開発してきます。(日本オラクル Fusion
Middleware事業統括本部 関屋信彦)

Restful Webサービスについて

Restful Webサービスの特徴やアーキテクチャについては既に多くの公開情報があるため、詳細は省きます。ここでは今回のアプリケーションを開発するにあたって関連するRestful Webサービスのポイントを押さえておきます。


  • クライアントとサーバーのやりとりは、HTTPのGET/POST/PUT/DELETE/HEADのメソッドを使います。従来のWebサービスやWebサイトでは主にGETとPOSTのみでした。
  • RESTful WebサービスはURIを意識しアーキテクチャです。URIのパスが処理対象(リソースと呼びます)を表します。そして、そのリソースに対しての操作は各HTTPメソッドを使い分けて行います。
  • RESTful Webサービスは基本的にステートレスです。つまりHTTPセッションを利用しません。これでより多くのリクエストを処理でき、また拡張性を高めることができます。

JAX-RSについて

JavaEE 6におけるJAX-RSのバージョンは1.1です。JAX-RSを使うことで、Javaの標準的なAPIとしてRestful Webサービスのシステムを開発することができるようになります。このAPIの特徴をいくつか挙げます。


  • POJOのJavaクラスにURIパスを定義するアノテーションをつけてWebサービスのリソースとJavaクラスやメソッドのマッピングを行います。
  • HTTPメソッドに対応したアノテーション(@GET/@POST/@PUT/@DELETEなど)が用意されています。これで簡単にJavaのメソッドをRestful Webサービスとして公開できます。
  • メディアタイプ(表現形式)もアノテーションで制御します。メディアタイプによってHTTPリクエスト・レスポンスのボディにHTMLを使うか、XMLを使うかなど変えることができます。

WebLogic Server 12cのJAX-RS

WebLogic Server 12cではJAX-RSの実装としてJerseyのバージョン1.9を利用しています。JerseyはJAX-RS 1.1のリファレンス実装であり、実績のあるオープンソースです。よって、WebLogic Server上でJAX-RS開発を始めたい場合、Jerseyのドキュメントが参考となります。また、WebLogicのドキュメントの「RESTful Webサービスの開発」も適度な分量で書かれているので、これから初めてJAX-RSを開発する方はこちらの方が読みやすいかもしれません。また、JAX-RSのサンプルアプリケーションを探している場合は、Jerseyが提供するサンプルを一度ダウンロードしてみるといいでしょう。WebLogic Server12cの中に含まれているJerseyのバージョンはアップグレードが可能です。詳しくは「RESTful Webサービスの開発」を参照してください。

このブログの内容

JAX-RSの第1回では、JAX-RSアプリケーションを開発しながらJAX-RS開発のポイントについて学び、最後にWebLogic Server12cにデプロイして実際に動きを確認します。


  • 簡単なメッセージ投稿サイトを題材にしたアプリケーションを作成します。
    • ユーザーはHTTPのPUTでメッセージを投稿できます。
    • ユーザーはHTTPのGETで自分や他の人のメッセージを取得できます。
  • アプリケーションをWebLogic Server12cにデプロイします。
  • curlを使ってJAX-RSアプリケーションの動きを確認します。

アプリケーション開発の準備

本連載では、Oracle Enterprise Pack for Eclipse(OEPE)を使用してサンプル・アプリケーションの開発を進めます。OEPEやWebLogic Server 12cのインストールおよび設定が終わっていない方は、記事「[連載] WebLogic Server 12cでJava EE 6を動かしてみよう!(1) 概要」を参考にしてください。

図1: 「New Dynamic Web Project」ウィンドウ1
図1: 「New Dynamic Web Project」ウィンドウ1(クリックして拡大)


OEPE起動後にまず今回のアプリケーション用のEclipseのプロジェクトを作成します。「New」->「Dynamic Web
Project」を選択します。「New Dynamic Web Project」ウィンドウが表示されたら、「Project
Name」としてここでは「JaxRsSample1」を入力し、「Next」ボタンをクリックします。その次の画面ではそのまま「Next」を押してく
ださい。

図2: 「New Dynamic Web Project」ウィンドウ2
図2: 「New Dynamic Web Project」ウィンドウ2(クリックして拡大)

次に表示される画面では「Generate web.xml deployment descriptor」にチェックを入れて最後にFinishでプロジェクトの作成を完了してください。

図3: 「Properties - Project Facets」ウィンドウ
図3: 「Properties - Project Facets」ウィンドウ(クリックして拡大)

プロジェクトが作成されたら、次にEclipse上でJAX-RSのAPIを参照できるように、参照ライブラリをプロジェクトに追加します。
EclipseのProject
Explorerにてプロジェクト名JaxRsSample1を選択し、右クリックから「Properties」を選択してください。表示されたダイアロ
グの左側のペインで「Project Facets」を選択します。Project Facets画面では「JAX-RS (REST Web
Services)にチェックを入れます。そして、「Futther configuration required…」のところをクリックします。

図4: Project FacetsからのJAX-RSライブラリの追加
図4: Project FacetsからのJAX-RSライブラリの追加(クリックして拡大)

ここではJAX-RSの実装ライブラリを指定します。ライブラリ追加のボタンをクリックします。

図5: ライブラリ名の入力
図5: ライブラリ名の入力(クリックして拡大)

「New」ボタンを押します。「User library name」にはここではJAX-RSと入力します。OKを押します。

図6: JAR追加ボタン
図6: JAR追加ボタン(クリックして拡大)

「Add
JARS…」をクリックします。ファイルの選択ダイアログになるので、<ミドルウェアホーム(D:\wls12c)>\modules
\com.sun.jersey.core_1.1.0.0_1-9.jarを選択して追加します。jarが追加されたことを確認し、「OK」をクリック
します。

図7: JAX-RS ライブラリ反映後のProject Facets画面
図7: JAX-RSライブラリ反映後のProject Facets画面(クリックして拡大)

戻った画面では忘れずにJAX-RSライブラリの横のチェックボックスにチェックを入れます。その後は、JAX-RSのサーブレットとURLマッピ
ングの 情報を確認してください。この内容がweb.xmlに反映されます。ここではデフォルトのままにして、「OK」をクリックしてください。
「Projects Facets」画面に戻りますので、そこでも「OK」をクリックしてファセットの反映を確定させてください。

プロジェクトの作成とプロジェクト・ファセットの追加が終わった段階で、以下のファイルが自動的に作成されています。これの他にもファイルやライブラリはありますが、ここでは説明を割愛します。


  • Java Resource -> Libraries -> JAX-RS

    さきほどファセットから追加したJAX-RSのライブラリです。これで今回のEclipseでの開発で、JAX-RSのAPIを参照できるようになりました。
  • WebContent/WEB-INF/web.xml

    さきほどのJAX-RS関連のサーブレット定義が追加されています。
  • WebContent/WEB-INF/weblogic.xml

    WebLogic Server固有のデプロイメント・ディスクリプタです。特にJAX-RS関連の設定はここにはありませんがWebLogicサーバーにデプロイするときに必要なファイルです。

アプリケーションの作成 web.xml

これからJAX-RSのアプリケーションを作っていくための手順を説明します。まずはHTTPリクエストを受けつけるところの部分です。これまでの手順によって、web.xmlのサーブレット定義部分は以下の状態になっています。

web.xml(抜粋)
  <servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping>

JerseyのサーブレットがURLパス/jaxrsでリクエストを受け付けています。このURLパスは変更可能ですが、今回はこのままにしておきます。

アプリケーションの作成 Restful Webサービス設計

次に、Restful
Webサービスとしての設計です。リソースとそのリソースが公開するHTTPメソッドを決めます。各リソースはURIで表現され、その実体はJAX-RS
の場合、JavaのクラスまたはJavaメソッドになります。今回は簡単なメッセージ投稿Webサービスを題材にして設計します。










URIパス(リソース)HTTPメソッド説明
/messagesGETWebサービス内の全メッセージを表すリソースです。GETにより一覧を取得できます。
/messages/uid-{userid}
例: /messages/uid-sekiya123
GET/PUT指定されたユーザーIDの全てのメッセージを表すリソースです。PUTによりそのユーザーのメッセージを投稿できます。
/messages/uid-{userid}/seq-{usermessageid}
例:/messages/uid-sekiya123/seq-1
GET各ユーザーの個々のメッセージを表します。ユーザー内で一意なユーザーメッセージIDで指定します。

今回は取り扱いませんが、HTTPメソッドとしてはこの他にPOST/DELETE/HEADなどがあります。POSTとPUTの違いは、PUTは
多重呼び出し不変(idempotent)な場合に使い、そうでない場合はPOSTを使うべきとされています。HEADはHTTPヘッダのみダウンロード
する場合に使います。

アプリケーションの作成 JAX-RS開発

ここからJAX-RSのリソースを作成していきます。リソースはJAX-RSではPOJOのクラスとして作成します。クラスがJAX-RSのリソー
スとして扱われるためには、@Pathをクラス宣言の上に付け加えるだけです。この@Path内に対応のURIパスを書きます。

まずは/messagesのリソースクラスです。URIパスの一番上のリソースとなるので、ルートリソースと呼ばれます。Eclipseプロジェク
トを右クリックし、「New」→「Class」でPackage欄に「jaxrssample1.resource」、Nameに
「MessagesResource」と入力します。その他は変更せずに「Finish」を押します。クラスが作成されたら、クラス宣言の上に@Path
でURIパスを指定しましょう。

MessagesResource.java [1]
package jaxrssample1.resource;
import javax.ws.rs.Path;
@Path("/messages")
public class MessagesResource {


}

/messages に対するHTTP GETの処理を書く前に、先に/messages/uid-{userid}に該当するリソースクラスとそれに対するPUT処理を作成し、メッセージを投稿できるようにしたいと思います。

/messages/uid-{userid}のリソースは、/messagesのサブリソースとなります。サブリソースは、JAX-RSでは元の
リソースクラス(この場合MessageResource.java)から呼び出される別のリソースクラス(サブリソースクラス)か、元のリソースクラス
の中の一つのJavaメソッド(サブリソースメソッド)として実装できます。今回はサブリソースクラスとして作成します。サブリソースクラスを呼び出す元
のリソースクラス側のJavaメソッドをサブリソースロケータと呼びます。

では、まずはサブリソースロケータとしてgetUserMessagesのメソッドをMessageResourceクラスに追加します。このメ
ソッドがJAX-RSのサブリソースロケータとして認識されるためには、メソッドに対して@Pathをつけてサブリソースのパス
(uid-{userid})を書きます。このパスはuid-の4文字でこの部分のパスが始まる必要があることを示しています。{}で囲まれた部分は
@PathParamを使うことで実際の送信URI上の{}の中身を取得できます。例えば、送信されたURIが/messages/uid-abc123
の場合、@PathParamを利用することでabc123の部分を取得できます。今回はこの部分をユーザーIDとして取り扱います。今回"uid-"を
ユーザーIDの前にわざわざつけたのは、@Pathの定義方法をを色々紹介するということが念頭にありましたが、その他に実際の使い方として、今回のよう
にURIの中にユーザーIDを指定する以外のオプションとして、ユーザー名などで指定したい場合に、URIパスを
「"uname-{username}"」とするなどが考えられます。なお、今回はユーザーIDのみでユーザー名は使わないアプリケーションとしていま
す。

さきほどの@PathParamは、リソースロケータメソッドの引数に配置する形となります。今回はパスから取得したユーザーIDをサブリソースク
ラスにコンストラクタの引数として渡しています。見てわかる通り、サブリソースクラスは単純にサブリソースロケータメソッドの中でnewするだけで、特別
なことはしていません。

MessagesResource.java [2]
package jaxrssample1.resource;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@Path("/messages")
public class MessagesResource {


@Path("/uid-{userid}")

public UserMessagesResource getUserMessages(@PathParam("userid") String userid) {

return new UserMessagesResource(userid);

}
}

UserMessagesResourceクラスはまだ作成していないので、「public UserMessagesResource
getUserMessages」の横に×印が表示されると思います。×印をクリックすることで表示されるダイアログから「Create class
UserMessagesResource」を選択し、同じjaxrssample1.resourceパッケージ配下のクラスとして作成してください。
次に、「return new UserMessagesResource(userid);」の横の×印をクリックし、「Create
constuructor(…省略)」を選択してコンストラクタも追加してください。

次に、ユーザーメッセージの投稿によるWebサービスへの更新処理の実装を行います。/messages/uid-{userid}のパス上での
HTTP
PUTとして実現されるようにします。まず、作成したUserMessagesResourceクラスのsetUserMessageというJavaメ
ソッドを書きます。そしてこのメソッドに@PUTをつけます。これでこのURIに対するHTTP
PUTが行われたときにこのメソッドが呼ばれるようになりました。追加として、今回はJSON形式のデータのみを受け付けるようにするため、
@Consumes("application/json")もメソッドの上につけます。データの表現形式はメディアタイプと呼ばれ、このようにクライア
ントからのデータを受け取るときの表現形式は@Consumesで指定し、Javaメソッドの戻り値としてクライアントに返すときの表現形式は
@Producesで指定します。これらを指定しない場合はどのメディアタイプのものでも受け付けることになります。他のメディアタイプとしては
text/plain, application/xmlなどあり、これ以外にもたくさんあります。

UserMessagesResource.java
package jaxrssample1.resource;
import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import jaxrssample1.db.StaticMemory;
import jaxrssample1.model.Message;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
public class UserMessagesResource {

private String userid;


public UserMessagesResource(String userid) {

this.userid = userid;

}


@PUT

@Consumes("application/json")

public void setUserMessage(JSONObject jsonEntity) throws JSONException {

Message msg = new Message();

msg.setUserid(userid);

int usermessageid = 0;

if (!jsonEntity.isNull("usermessageid")) {

usermessageid = jsonEntity.getInt("usermessageid");

}

msg.setUserMessageId(usermessageid);

msg.setPosttime(new java.util.Date());

msg.setTitle(jsonEntity.getString("title"));

msg.setMessage(jsonEntity.getString("message"));


StaticMemory.putMesasge(msg);

}
}

今回は「RESTful Webサービスの開発
を参考にして、JSON形式をリクエストとレスポンスのデータ形式にします。JSONは、XMLよりもデータ量が少なく、読みやすい形式のデータです。
JavaScriptとの親和性が高く、クライアントからも利用しやすいです。今回使うJSON用のライブラリはJerseryが利用しているものを使い
ます。Eclipseでの開発時にこのAPIを参照できるようにするにはライブラリの追加が必要なので、これからその手順を行います。



図8: JSONライブラリの追加
図8: JSONライブラリの追加(クリックして拡大)

プロジェクトJaxRsSample1のトップフォルダを右クリックしPropertiesを選択します。Propertiesの左ペインでは
「Java Build Path」を選択します。そして右側に表示される画面では「Add Library…」をクリックします。

図9: JSONライブラリ追加後の状態
図9: JSONライブラリ追加後の状態(クリックして拡大)

Add Library画面では「User Library」を選択し、Nextを押します。次に「User
Libraries…」ボタンを押します。表示される入力ボックスには、ここでは「JSON」と入力します。そして、JSONを選択した状態で「Add
JARs…」ボタンをクリックし、ファイルダイアログからは<ミドルウェアホーム(D:\wls12c)>\modules
\org.codehaus.jettison_1.0.0.0_1-1.jarを選択します。この段階で、図の状態になります。OKを押し、戻った
「User
Library」画面ではJSONにチェックをつけて「Finish」をクリックします。そして、Propertiesダイアログに戻ったら最後にOKで
確定させてください。

 最初のJAX-RSライブラリでも同じことが言えまが、これらのライブラリはWebLogic
12cの中のインストールに含まれています。つまり実行時にシステムクラスローダー上で読み込まれるようになっているため、warをデプロイするときには
これらをわざわざwarの中に含める必要はありません(つまり、WEB-INF/libに入れる必要はありません)。(ただし、jerseyのライブラリ
をアップグレードしたい場合は別です。)

JSONObjectのクラスがEclipse開発画面上で参照できるようになったところで、ここで一つ疑問が生じます。HTTPで送られてきた
JSON形式のデータがどうやってJSONObjectのインスタンスに変換されたのでしょうか?答えは、この変換部分の処理はJAX-RSのエンティ
ティプロバイダと呼ばれる分類のクラスによって行われます。HTTPリクエストを受け取る際のエンティティプロバイダはJAX-RS
APIのjavax.ws.rs.ext.MessageBodyReaderインターフェースを実装しています。HTTPレスポンスを返す際のプロバイ
ダはjavax.ws.rs.ext.MessageBodyWriterインターフェースを実装しています。JAX-RSの仕様では、各JAX-RS実
装が標準的にサポートしなければいけないとされているJavaの型とそれに対応したメディアタイプが決まっています。詳細はJAX-RS1.1の仕様書
確認できますが、String型やbyte[]型の他、javax.xml.bind.JAXBElementといったJAXBの型などがあります。これ
らの型であれば、どのJAX-RS実装製品を利用しても、正しいJavaクラスへの変換が自動的に行われます。これら以外のJavaクラスに変換するに
は、利用するJAX-RS実装が独自にMessageBodyWriter実装を提供しているか、自分で書く必要があります。今回のJSONObject
はこのタイプのもので、このカスタムのエンティティプロバイダはJerseyのライブラリの中で提供されています(よってWebLogicでも同じライブ
ラリが使用できます)。

今回は、setUserMessageメソッドの中では、送られてきたJSONObjectのメッセージ情報を
jaxrssample1.model.Messageクラスとして表現形式に依存しない独立した型に変換し、メッセージの保存をしています。この永続化
処理の部分は、手順簡略化のためにデータベースなどは使わずにstaticな変数に格納しているだけです。名前の通り、StaticMemoryというク
ラスを使ってメモリに保存しています。(よってアプリケーションサーバーを再起動するとデータはなくなってしまいます)。新しく作成するMessageと
StaticMemoryはJAX-RSとは直接は関係のないコードですので、掲載のコードをコピーして作成ください。Message.javaはコピー
したのち、Message.javaファイル上で右クリック→「Source」→「Generate Getters and Setters
…」と選択して全ての属性にチェックを入れてOKで確定してsetterとgetterを追加してください。その後に、同じように
Message.javaファイル上で右クリック→「Source」→「Generate hashcode() and equals()
…」を選択して、一意キーとなるuseridとuserMessageIdにだけチェックを入れてOKで確定してください。

Message.java
package jaxrssample1.model;
import java.util.Date;
public class Message {

private String message;

private String userid;

private Date posttime;

private int userMessageId;

private String title;
}
StaticMemory.java
package jaxrssample1.db;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jaxrssample1.model.Message;
public class StaticMemory {

//useridをキーにそのuserのメッセージが全て入ったMapが取得できます

//取得されたMapはuser毎のシーケンス番号(=usermessageid)がキーです。

private static Map<String, Map<Integer, Message>> messageMap = new HashMap<String, Map<Integer, Message>>();

public static void putMesasge(Message msg) {

Map<Integer, Message> userMessagesMap = messageMap.get(msg.getUserid());

if (userMessagesMap == null) {

userMessagesMap = new HashMap<Integer, Message>();

messageMap.put(msg.getUserid(), userMessagesMap);

}

if (msg.getUserMessageId() == 0) {//新規メッセージの場合. IDは1からはじめる

msg.setUserMessageId(userMessagesMap.size() + 1);//メッセージのDELETEはなしという前提

msg.setPosttime(new java.util.Date());

}

userMessagesMap.put(msg.getUserMessageId(), msg);

}

public static Message getMessage(String userid, int usermessageid) {

Map<Integer, Message> userMessages = messageMap.get(userid);

if (userMessages == null) {

return null;

}

return userMessages.get(usermessageid);

}

public static List<Message> getMessage(String userid) {

Map<Integer, Message> msgs = messageMap.get(userid);

if (msgs == null) {

return null;

}

return new ArrayList<Message>(msgs.values());

}

public static List<Message> getAll() {

List<Message> allMessages = new ArrayList<Message>();

Collection<Map<Integer, Message>> userMsgs = messageMap.values();

for (Map<Integer, Message> map : userMsgs) {

allMessages.addAll(map.values());

}

return allMessages;

}
}

次に、最後の/messages/uid-{userid}/seq-{usermessageid}に対応するリソースクラス
UserMessageObjResourceを、先ほど作成したUserMessagesResourceクラスから呼び出します。前と同じようにここ
でもサブリソースロケータ(getUserMessageObj)のJavaメソッドを作成し、そこからサブリソースクラス
(UserMessageObjResource)のインスタンスをnewで生成します。そしてここでも@PathParamを利用してURLの
set-{usermessageid}の{}で囲まれた部分の文字列を取得してコンストラクタに渡します。

UserMessagesResource.java [2] (追加)

@Path("seq-{usermessageid}")

public UserMessageObjResource getUserMessageObj(@PathParam("usermessageid") int usermessageid ) {

return new UserMessageObjResource(userid, usermessageid);

}

次に、前と同じようにエディタで赤くなった×印をクリックして、未作成のUserMessageObjResourceクラスとそのコンストラクタ
を追加してください。このリソースのURI
(/messages/uid-{userid}/seq-{usermessageid})に対してのHTTP
GETで、そのユーザーの投稿したメッセージをID指定で取得するようにします。(IDといっても実際はただのシーケンス番号です。URIのseqはその
意味でつけています)。この取得処理を行うJAX-RSのリソースメソッドとして、UserMessageObjResourceクラスに対して
getMessageメソッドを追加し、@GETを加えることでHTTP
GETで呼ばれるようにします。getMessageメソッドの中では、StaticMemoryからURIパスで指定されたシーケンスIDに該当した
Messageクラスのインスタンスがあれば取得し、JSONObjectという型の戻り値を返します。JSONObjectのインスタンスは、この後作
成するユーティリティクラスMessageJSONBind.javaを介してMessageクラスのインスタンスを元に作成します。
JSONObjectは先ほど追加したライブラリorg.codehaus.jettison_1.0.0.0_1-1.jarの中に含まれるクラスで
す。MessageJSONBind.javaは掲載コードをコピーして作成してください。

GETをつけたリソースメソッドの戻り値がHTTPレスポンスとなります。JSP、JSFのようにHTMLファイルのような媒体を作成するステップ
はありません。どういった表現で返すかはメディアタイプで指定しますが、意図したとおりに変換できるかどうかは前に説明したエンティティプロバイダの
MessageBodyWriterのインターフェースを実装したプロバイダによります。今回はJerseyのライブラリのおかげでJSONObject
型を戻り値として取り扱うことができています。返すことができるデータ形式はこのJSON形式だけのため、@ProducesでJSONのメディアタイプ
を指定するのを忘れないようにしましょう。

ここでもしURLで指定されたIDのメッセージがなかったら、戻り値としてnullを返すようにしています。nullが返った場合、どのようなHTTPレスポンスとなるかは後ほどのテストで確認してみます。

UserMessageObjResource.java
package jaxrssample1.resource;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import jaxrssample1.db.StaticMemory;
import jaxrssample1.model.Message;
import jaxrssample1.util.MessageJSONBind;
import org.codehaus.jettison.json.JSONObject;
public class UserMessageObjResource {

private String userid;

private int usermessageid;


public UserMessageObjResource(String userid, int usermessageid) {

this.userid = userid;

this.usermessageid = usermessageid;

}


@GET

@Produces("application/json")

public JSONObject getUserMessage() {

Message msg = StaticMemory.getMessage(userid, usermessageid);

if (msg == null) {

return null;

}

return MessageJSONBind.getJSON(msg);

}
}
MessageJSONBind.java
package jaxrssample1.util;
import jaxrssample1.model.Message;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
public class MessageJSONBind {

public static JSONObject getJSON(Message msg) {

try {

return new JSONObject().put("userid", msg.getUserid())

.put("usermessageid", msg.getUserMessageId())

.put("title", msg.getTitle())

.put("message", msg.getMessage())

.put("posttime", msg.getPosttime());

} catch (JSONException je) {

return null;

}

}
}

アプリケーション・テスト

作成したアプリケーションを実行してみましょう。 「Project
Explorer」ペインで「JaxRsSample1」を右クリックし、「Run as」→「Run on Server」を選択します。 「Run
on
Server」ウィンドウが表示されたら、実行に使用するWebLogicドメインを選択し、「Finish」ボタンをクリックします(このとき、
「Always use this server when running this project」をチェックしておくと、次回からは「Run
on Server」ウィンドウがスキップされて便利です)。



図10: WebLogic Server12c起動時のログ
図10: WebLogic Server12c起動時のログ(クリックして拡大)

起動時はEclipseのコンソールでRUNNINGの表示で正常に起動したことと、JAX-RSのルートリソースが検知されたことのログを確認してみてください。

図11: curlダウンロードサイト
図11: curlダウンロードサイト(クリックして拡大)

起動が確認できたらいよいよテストですが、今回はHTTPクライアントとなるWebサイトのHTMLやJavaScriptやHTTPクライアントアプリケーションは作成していません。よってテストにはcurlというツールを使います。こちらのURLhttp://curl.haxx.se/download.htmlからご自分の操作環境にあったパッケージをダウンロードしてください。筆者はWin64版のSSLでないものをダウンロードしました。

Windows環境の場合、zipファイルをC:\Program Files\curlなどの適当なフォルダに解凍し、curl.exeが配置されたファイルに対して環境変数のPATHを通すといいでしょう。ここからはPATHが通っているものとして説明します。

Windowsのコマンドプロンプトを開いてください。適当なフォルダに移動し、テキストファイルに送信するJSONのデータを書きます。ここではファイル名をput_msg1.jsonとします。

put_msg1.json
{

"message":"Is this going to end??",

"title":"today tweet"
}

curlのコマンドラインで上のファイル名を@で指定し、以下のようにcurlでWebサービスにHTTPのPUTリクエストを出します。useridとしてabc001という値を指定しています。

curl -X PUT -i -H "Content-type: application/json" -d @put_msg1.json  http://localhost:7001/JaxRsSample1/jaxrs/messages/uid-abc001

下のような結果が出力されれば成功です。レスポンスコードが204であり、400番や500番台でないことを確認します。@PUTのリソースメソッ
ドの戻り値がvoidのため、204 No Contentとなっています。また、HTTPボディ部も空のため、Content-lengthが0です。

HTTP/1.1 204 No Content
Date: Thu, 11 Apr 2013 14:00:30 GMT
Content-Length: 0
X-Powered-By: Servlet/3.0 JSP/2.2

次に、いまPUTしたデータをGETで取得してみましょう。

curl -X GET -i -H "Accept: application/json" http://localhost:7001/JaxRsSample1/jaxrs/messages/uid-abc001/seq-1

以下のような出力になるはずです。

HTTP/1.1 200 OK
Date: Thu, 11 Apr 2013 14:23:16 GMT
Transfer-Encoding: chunked
Content-Type: application/json
X-Powered-By: Servlet/3.0 JSP/2.2
{"userid":"abc001","usermessageid":1,"title":"today tweet","message":"Is this going to end??","posttime":"Thu Apr 11 23:22:24 JST 2013"}

存在しないuseridまたはusermessageidをURLパスに指定してみましょう。Not Foundでレスポンスコードが404となります。リソースメソッド@GETに対してnullを返した場合はこのようなレスポンスとなります。

HTTP/1.1 404 Not Found
Date: Thu, 11 Apr 2013 14:25:47 GMT
Content-Length: 9
Content-Type: text/html; charset=UTF-8
X-Powered-By: Servlet/3.0 JSP/2.2
Not Found

まとめ

今回は簡単なサンプルを通じて、Restful Webサービスの設計と、JAX-RSを使っての実装について実践しました。また、WebLogic12cのJAX-RSでJSON形式のデータを扱うための方法について説明しました。

次回は今回のサンプル開発の続きを行います。JAXBを使ってのXMLやJSONの入出力や、Jerseyライブラリのアップグレード、JAX-
RSのUriBuilderやResponseクラスを利用して機能を追加していきます。

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.