12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaEEでRESTfulアプリケーション構築

Posted at

まずはRESTfulアプリケーションのおさらい

RESTとは、REpresentational State Transfer の略でWebアプリケーションの設計思想です。RESTfulとは、REST の規約に従ったWebサービスのことです。

RESTで大事なのは、

  • リソース指向
  • 統一インターフェース
  • ステートレス

という点です。

リソース指向

サービスを提供するために、システムのリソースをAPIを通して公開します。このAPIはURIのパスになります。**URIのパス名はとっても重要です。**パス名の良し悪しがサービスの良し悪しになります。
リソースの意味が直感的に分かるように名詞を付けていきます。より特定な情報をやり取りする場合は階層を用います。パスは短く簡潔にし、名詞同士をくっつけたり、名詞と動詞をくっつけたようなパス名にならないようにしましょう。

ブック一覧
[GET]http://exsample.jp/book/
特定のブック
[GET]http://exsample.jp/book/1234
[GET]http://exsample.jp/book/name/書籍名
作成
[PUT]http://exsample.jp/book/
更新
[POST]http://exsample.jp/book/1234
削除
[DELETE]http://exsample.jp/book/1234

NG例
[GET]http://exsample.jp/bookname/書籍名
[DELETE]http://exsample.jp/deletebook/xxx

統一インターフェース

HTTPのメソッドを使ってアクセスします。

メソッド 役割
GET リソースの取得。GETでのアクセスはリソースの内容に影響を与えない
POST リソースの新規作成
PUT 既存のリソースの更新
DELETE リソースの削除

ステートレス

サーバー側でもっている状態に依らずいつでも同じ意味合いのやり取りが出来ることが大事です。同じ意味合いなので、必ずしも同じ情報とは限りません。価格といった情報は変動しますが、そういった付加情報的なものは変動します。仕組みで云えば、例えばクッキーや隠しパラメータといったURI以外の仕組みを持たないことです。
ところで、セッション情報で権限を持たないロールには限定的な情報しか返さないということはしたことあるけど、これもNGなのかな?

データベース設計

リソースの永続化はRDBだろうとNoSQLだろうとファイルだろうと何でも構いませんが、今回はRDBを扱います。

ORマッパーには

  • 先にコードで定義したエンティティクラスからテーブル生成
  • 先にデータベースでテーブルを定義し、コードを生成

というどちらかの方法がとれますが、今回は後者の方で進めます。

テーブル設計で大事なのは参照整合性を保つことです。
SQLアンチパターンを読むと詳しく解説されています。テーブル設計で外部結合や制約を適切に活用することで、アプリケーションで余計な実装をしなくても良くなります。ただし、逆の考え方もあって、むやみやたらに参照整合性制約を使わずに、アプリケーション側で参照整合性を保つという手もあります。テーブル設計をガチガチにすると柔軟性が低くなるという理由ですね。Railsなんかはアプリケーション側の責務としていますね。

JavaEEのテクノロジー

JavaEE7で含まれるテクノロジーの一部です。いろいろあって大変そうに見えますが、それぞれがRESTの仕様、ORMの仕様、DIの仕様っていう風に分割統治で役割がはっきりしています。

JavaEE7.png

機能 対象領域 役割
JSF プレゼンテーション層 HTML5対応のWebページのフレームワーク
WebSocket サービス公開 双方向通信のフレームワーク
JAX-RS サービス公開 RESTのフレームワーク
JSON-P 転送 JSONオブジェクト生成
JAXB 転送 XMLオブジェクト生成
EJB ビジネス層 ビジネスロジックに使用。トランザクション管理を備える
JPA 永続化層 ORマッパーフレームワーク
CDI 全領域 DIフレームワーク

システムの開発環境

今回は以下の環境で構築しますが、好きな組み合わせで構いません。
インストール手順や設定については端折ります。

  • OS:Windows
  • Java:Java SDK 8u92 64bit
  • 統合開発環境:NetBeans 8.1 64bit
  • アプリケーションサーバー:Apache TomEE 7.0.0-M3
  • データーベース:PostgreSQL 9.4.8 64bit
  • JDBCドライバ:JDBC 42 9.4 Build 1208
  • プロジェクト管理ツール:Maven 3.3.9
  • REST確認ツール:Fiddler

アプリケーションサーバーですが、JavaEE7に対応しているものを選択する必要があります。
Apache TomEE 7はまだ開発版なので、お試しであればGlassFishを使えばよいですが、参照実装なので本番環境では利用できません。また、RESTだけであればJavaEE6でも十分なので、他にもいくつかの選択肢があります。

RESTサービス構築手順

  1. テーブル定義
  2. JavaEEプロジェクト作成
  3. データーベースからエンティティクラス、RESTサービスクラスの作成

基本的な流れはこれだけですね。
NetBeansを使うといろいろ自動化されているので便利です。

JavaEEプロジェクト作成
JavaREST1.png

エンティティとRESTサービスクラスの作成
JavaREST2.png

ここで3つのクラスが生成されます。

Applicationクラス
@ApplicationPath:アプリケーションをWebサービスに配置する場合のトップパスを設定します。サービスを表す名前をつけましょう。

ApplicationConfig.java
@javax.ws.rs.ApplicationPath("service")
public class ApplicationConfig extends Application {
	
	
}

Entityクラス
JPAのO/Rマッピングを行うエンティティです。
いくつかのアノテーション定義だけで関連付けができます。
@Enitity@Table@Id@NotnNull@Column@Size:データベースと関連付けるための定義
@XmlRootElement:XML/JSONとオブジェクトのシリアライズとデシリアライズを行うための定義

BookEntity.java
@Entity
@Table(name = "userentity")
@XmlRootElement
public class Userentity implements Serializable {
  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Basic(optional = false)
  @NotNull
  @Column(name = "id")
  private Long id;
  @Size(max = 255)
  @Column(name = "name")
  private String name;
  @Size(max = 255)
	
	
}

Restサービスクラス
@Path:リソース名を定義します。クライアントからアクセスする場合は@ApplicationPathと組み合わさり、http://exsample.jp/service/users となります。
@Path("{id}"):リソースに対して更に詳細なアクセスを提供します。
@PathParam("~~~"):パスパラメータを取得します。
@POST@PUT@DELETE@GET:リソースの操作を割り当てます
@Consumes@Producess:リソースが受け付けるMIMEタイプ、リソースから返されるMIMEタイプを指定します。

BookServiceRest.java
@Stateless
@Path("users")
public class UserentityFacadeREST extends AbstractFacade<Userentity> {
  @PersistenceContext(unitName = "adtekfuji_TestJavaEE_RESTServer_war_1.0PU")
  private EntityManager em;

  public UserentityFacadeREST() {
    super(Userentity.class);
  }

  @POST
  @Override
  @Consumes({"application/xml","application/json"})
  public void create(Userentity entity) {
    super.create(entity);
  }

  @PUT
  @Path("{id}")
  @Consumes({"application/xml","application/json"})
  public void edit(@PathParam("id") Long id, Userentity entity) {
    super.edit(entity);
  }

  @DELETE
  @Path("{id}")
  public void remove(@PathParam("id") Long id) {
    super.remove(super.find(id));
  }

  @GET
  @Path("{id}")
  @Produces({"application/xml","application/json"})
  public Userentity find(@PathParam("id") Long id) {
    return super.find(id);
  }

  @GET
  @Override
  @Produces({"application/xml","application/json"})
  public List<Userentity> findAll() {
    return super.findAll();
  }

  @GET
  @Path("{from}/{to}")
  @Produces({"application/xml","application/json"})
  public List<Userentity> findRange(@PathParam("from") Integer from, @PathParam("to") Integer to) {
    return super.findRange(new int[]{from, to});
  }

  @GET
  @Path("count")
  @Produces("text/plain")
  public String countREST() {
    return String.valueOf(super.count());
  }

  @Override
  protected EntityManager getEntityManager() {
    return em;
  }
  
}

RESTを確認する

Chrome では Advanced REST clientとかDHC REST ClientといったアプリでRESTの確認が出来ますが、アクセスした履歴を残してほしかったり、いろんな形式でデータを見たければ「Fiddler」というツールがお薦めです。Webプロキシとしてのツールなので、HTTP(S)のあらゆる情報が確認できます。

fiddler.png

12
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?