読者です 読者をやめる 読者になる 読者になる

ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

ThreeTenABP と ThreeTenBP の関係について (Android における JSR-310 バックポート)

Android アプリ ライブラリ

「ThreeTenABP って Android フレームワークに依存するけど、ドメインレイヤとかで Android 依存を排除したい場合どうするのがいいんですかね」 という相談を受けて、ThreeTenABP 周りを調べたのでメモ。

ThreeTenABP って何?

JSR 310 Date and Time API 周りの話

ThreeTenABP が存在する意味は?

  • ThreeTen Backport (threetenbp) があるならそれでいいのでは? → ThreeTen Backport はタイムゾーン周りの情報を JAR から読み込むという仕組みになっており、Android では非効率。

というわけで

ThreeTenABP を使いたいけど Android フレームワークに依存させたくないというモジュールでは、ThreeTen Backport に依存させて、テストを書く際にタイムゾーン情報の扱いだけなんとかする、みたいなことをすれば良さそう。

タイムゾーン情報周りを厳密にテストしなくていいなら、compileOnly "org.threeten:threetenbp:${threetenbp_version}"testCompile "org.threeten:threetenbp:${threetenbp_version}" を依存に追加しちゃうのが手軽でいい気がする。 (バージョン周りはよしなに。 これでうまくいくだろうと思って書いてるけど特に何も確認はしてない。)

関連ページ

読んだ : .NET のエンタープライズアプリケーションアーキテクチャ 第 2 版 / Dino Esposito、Andrea Saltarello 著

ドメイン駆動開発 (DDD) 関係の読書会に参加していて、最近読んでいるのがこれです。

本書は、『再利用可能で、入手が容易な、ソフトウェアアーキテクチャの確かな知識ベースを提供』 することを考えて執筆されています。 すなわち、DDD の書籍というよりは、開発者とアーキテクトのための、ソフトウェアアーキテクチャ (その中でも特にエンタープライズアプリケーションや web アプリケーションのアーキテクチャ) の虎の巻のようなものです。 その中にドメイン駆動設計の考え方も含まれています。

内容

本書の内容を紹介します。

1 部 「基礎」 では、ソフトウェアアーキテクチャの基礎ということで、アーキテクトの役割であったり、プロジェクトを成功させるためにソフトウェアディザスタ (技術的負債だらけであること) を何故避ける必要があるのかといったこと、ソフトウェアの設計原則やテストが重要であることなどが書かれています。 ここら辺は割と他の書籍でも書かれていることなので、わりとサラッと読んでしまって良さそうです。 (ここら辺の内容をちゃんと吸収するなら 『CODE COMPLETE』 などを読むのが良いと思います。)

第 2 部 「アーキテクチャの考案」 には、プレゼンテーション層とビジネス層についてが書かれています。 目玉は 5 章の 「ドメインアーキテクチャの発見」 で、要約すると 『ドメインを深く理解することだけが適切なアーキテクチャの発見につながる』 ということと 『サブドメインの存在に気づいた場合は、それらをサブアプリケーションとしてモデリングし、最適なアーキテクチャをそれぞれに定義でき』 るということです。 ユビキタス言語と境界づけられたコンテキストが重要である、ということですね。

DDD 関係の本を読むとドメインモデルを構築するための技術的な部分に着目しがちですが、本書ではドメインモデルはあくまでサポートアーキテクチャの 1 つにすぎないと明確に述べていて、ユビキタス言語と境界づけられたコンテキストの重要性を前面に押し出しているのが特徴的です。 また、システムを設計するための手法として、ユーザーエクスペリエンスファースト (UX ファースト) と呼ばれるアプローチをとっているのも特徴ですね。 これは、システム設計の作業をプレゼンテーション層から開始して、予備的な分析を並行して行うという設計理念です。 つまり、最初にビジネスドメインと UX に関するデータを集めてユーザーとの対話モデルを設計して、その後でデータのワークフローやロジック、サービス、ストレージの定義に取り掛かるというものです。

第 3 部 「サポートアーキテクチャ」 では、ドメインモデル、CQRS、イベントソーシングの 3 つのサポートアーキテクチャについての説明がなされます。 ドメインモデルを用いた場合は、ドメインのすべての側面に適合する単一のモデルを設計する必要があり、モデルが複雑になってしまうという問題があるということが述べられ、本書ではやや CQRS 推しな感じです。 (もちろんドメインモデルが適している場面ではドメインモデルを使えば良いのですが。) 個人的にもドメインモデルをがっつり設計するのが常にいいとは思っていなかったので、「DDD の分析部分 (ユビキタス言語や境界づけられたコンテキストの発見) は常に重要だけど、戦略部分 (各境界づけられたコンテキストに最適なアーキテクチャを割り当てる) ではドメインモデルを使う以外の方法もある。 トランザクションスクリプトでもいいし、CQRS という選択肢もある」 というのを明確に示している本書は参考になりました。

第 4 部は 「インフラストラクチャ」 で、永続化レイヤーについて説明されます。

感想

DDD の 「分析部分」 と 「戦略部分」 を分けて、「戦略部分に置いてどういうアーキテクチャを選択するのが最適なのかは場合による」 というのを明確に示しているのが良いなーと思いました。 上でも書いたように、DDD というと 「ドメインモデルをいかに設計するのか」 に着目しがちなのですが、分析部分がまず重要であるというのが読んでいて伝わってきました。 (ユビキタス言語と境界づけられたコンテキストが重要であるということは DroidKaigi 2017 でのあんざいゆきさんの発表でもなされてましたね。)

戦略部分については、サポートアーキテクチャとして DDD において従来から使われているドメインモデルだけでなく、CQRS とイベントソーシングについても述べられているのが良い点だと思います。 どういうものかの紹介や思想の説明もありますし、実装の例も紹介されています。 実際に設計する際にどういう形にすればよいかがイメージしやすいようになっていて参考になります。

翻訳については、1 部の日本語が難しくなっていて読みづらいという問題はありました。 2 部以降はそれほど気にならなかったです。

全体としては、エンタープライズアプリケーションや web サービスの開発者やアーキテクトがアプリケーションのアーキテクチャについて検討する際に役立つ知識がまとまっていて、良い本だと思います。 『.NET の』 とタイトルにありますが、.NET に詳しくなくても問題なく読み進めていくことができますし、アプリケーションの全体のアーキテクチャについて考えている人は読んでみて損はないと思います。

Android のアカウントマネージャ (AccountManager) の概説

Android アプリ

最近 Android のアカウントマネージャを仕事で触ったので、調べた内容としてアカウントマネージャの概要をまとめておきます。

Web 上を調べると AccountManager を使う処理の実装方法はいろいろ見つかるのですが、アカウントマネージャの概要を説明しているページはあんまりなくて全体像を掴みにくいと思っています。 そういう情報を探している人の役に立てば幸いです。

公式ドキュメント

アカウントマネージャに関する公式ドキュメントは以下のものぐらいしかなさそうです。 AccountManager クラスのドキュメントを全て (各メソッドの説明も含めて) 読むと大体理解できると思います。 (下記ドキュメントを見て理解したら本ページの内容を読む必要はありません。)

アカウントマネージャの概要

アカウントマネージャは、Android のシステムがユーザーのオンラインアカウントを中央管理するための機能です。 Android 端末の 「設定」 にずらずらとアカウントが並ぶと思いますが、これもアカウントマネージャの仕組みで実現されています。

f:id:nobuoka:20170308031030p:plain:w360

各種オンラインサービスはそれぞれ異なったアカウントの扱い方や認証方式を使うため、アカウントマネージャはアカウント種別ごとに authenticator モジュールを使い分けるようになっています。

使いどころ

複数アプリで認証情報を共有するときに便利です。 (認証情報の提供側、および利用側両方とも。)

また、単一アプリでのみ認証情報を使う場合でも便利に使えると思います。 なぜなら、アカウントマネージャを使うことで認証周りの処理を分離しやすくなり、また、統一された方法で認証トークンを扱えるようになるためです。

用語

  • Account Type : Authenticator を特定するための文字列。
  • Auth token (認証トークン) : オンラインサービスのユーザー認証に使われるトークン。
  • Auth token type : Authenticator 固有の、Auth token 種別。 1 つのアカウントが auth token を複数持つことができる。
  • Feature : Authenticator 固有の、アカウントプロパティを特定するトークン。
  • Client (クライアント) / Application : アカウントマネージャを使って認証情報を取得するアプリを指す。
  • Authenticator : トークンの払い出しなどを行うやつ。 実体は AbstractAccountAuthenticator を継承したクラス。
    • システム上で有効な authenticator (AbstractAccountAuthenticator) を持っているアプリを指して Authenticator と言ったりもしてる? (明示的にアプリを表す場合は 「Authenticator アプリ」 と呼ぶのが良さそう。)
    • クライアントであり、かつ Authenticator であるというようなアプリも存在しうる。

Authenticator とクライアントの関係

アカウントマネージャを扱う処理を大別すると、authenticator とクライアントに分かれます。

  • Authenticator (や、それに関連する処理) : オンラインサービスのアカウント取得や認証処理を行います。 典型的には、ユーザーに対してログイン画面を表示してユーザー名とパスワードを入力させ、それらのアカウント情報を使ってオンラインサービスから認証情報を取得して、アカウントマネージャに渡します。 普通はそのオンラインサービスの提供者がアプリの中に実装します。
    • Authenticator のメソッドはアカウントマネージャから呼ばれます。
  • クライアント : アカウントマネージャを通じて、オンラインサービスの認証情報 (アクセストークンなど) を取得し、それを使ってオンラインサービスにリクエストを投げる、というような処理です。
    • 自社サービスクライアント : 自社が提供するサービスの認証情報をアカウントマネージャから取得します。 このアプリのシグネチャは、対応する authenticator を含むアプリのシグネチャと同じになります。
    • 他社サービスクライアント : 他社が提供するサービスの認証情報をアカウントマネージャから取得します。 このアプリのシグネチャは、対応する authenticator を含むアプリのシグネチャと異なります。

クライアントが AccountManager のクライアント向けのメソッドを呼ぶと、(一部のメソッドは) 対応する Authenticator のメソッドを呼びます。 そして、典型的には Authenticator のメソッドは AccountManager の Authenticator 用のメソッドを呼びます。 クライアントも Authenticator も AccountManager のメソッドを呼ぶという点で混乱しやすいのですが、AccountManager のメソッドをクライアント用メソッド群と Authenticator 用メソッド群に分けると、理解しやすいと思います。

f:id:nobuoka:20170308034440p:plain

自社サービスクライアントと他社サービスクライアントについて公式ドキュメント上での区別はありませんが、こういう分け方で考えると理解しやすいと思うので、本ページではこのように表記します。 ちなみに厳密な区別としては、「扱うアカウント種別の authenticator アプリと同じシグネチャを持つアプリ」 が自社サービスクライアント、「異なるシグネチャを持つアプリ」 が他社サービスクライアントです。

AccountManager のメソッド一覧

アカウントマネージャについて理解するには AccountManager クラスに生えている全てのメソッドを把握すればいいのですが、ドキュメントそのままだと理解しづらいので、整理して一覧できるようにしておきます。 これらのメソッド一覧に目を通すと、アカウントマネージャについての理解が深まるはずです。

API level 25 のドキュメントを参照しています。

クライアント向け

他社サービスのクライアントが使えるメソッド

Authenticator 一覧を取得したり、アカウント一覧を取得したり (パーミッションがあれば他社サービスのアカウントも全て)、指定のアカウントの認証トークンを取得したり、指定の認証トークンが無効になっていることをアカウントマネージャに伝えたり、ユーザーが指定のアカウントのパスワードを知っていることを確認するよう依頼したり、といったことができます。

  • getAuthenticatorTypes()
  • addOnAccountsUpdatedListener
    • アカウントマネージャが管理するアカウントの変化 (追加や削除など) を検知するリスナ (OnAccountsUpdateListener) を追加する。
    • getAccounts メソッドで取得可能なアカウントの変化のみ検知できる。 (典型的には、任意のアカウントの変化を検知するには GET_ACCOUNTS パーミッションが必要。)
  • removeOnAccountsUpdatedListener(OnAccountsUpdateListener)
    • リスナの削除。
  • addAccount
    • 指定のアカウント種別のアカウントを追加するよう依頼する。 対応する Authenticator が適切な UI でこのリクエストを処理する。
    • API level 22 以下では MANAGE_ACCOUNTS パーミッションが必要。
  • アカウント取得系
    • getAccounts
      • バイスに登録されているすべてのアカウントのリストを取得する。
      • ただし、GET_ACCOUNTS パーミッションがない場合は、同じシグネチャの Authenticator が管理するアカウントしか取得できない。
      • API level 22 以下の場合は GET_ACCOUNTS パーミッションが必要。 (ドキュメントに明記されてないけど多分。)
    • getAccountsByType
      • バイスに登録されているアカウントのうち、指定のアカウント種別のものを取得する。
      • GET_ACCOUNTS パーミッションがない場合は、同じシグネチャの Authenticator が管理するアカウントのみ取得できる。
      • API level 22 以下の場合は GET_ACCOUNTS パーミッションが必要。
    • getAccountsByTypeAndFeatures
      • バイスに登録されているアカウントのうち、指定のアカウント種別で、指定の機能をもつものを取得する。
      • 機能を考慮しないアカウント取得のメソッド (上 2 つ) とは違い、Authentcator が処理を行う。 (機能の管理をするため。)
      • GET_ACCOUNTS パーミッションがない場合は、同じシグネチャの Authenticator が管理するアカウントのみ取得できる。
      • API level 22 以下の場合は GET_ACCOUNTS パーミッションが必要。 (ドキュメントに明記されてないけど多分。)
  • confirmCredentials
    • ユーザーが指定のアカウントのパスワードを知っていることを確認する。 対応する Authenticator がこのリクエストを処理する。
    • 買い物処理みたいな、重要な操作の前に呼び出す、というような使われ方だと思う。
    • 呼び出し側がパスワードを渡した場合はそれが使われて、そうでなければ Authenticator 側がパスワード入力画面を表示する必要があるっぽい。
    • API level 22 以下では MANAGE_ACCOUNTS パーミッションが必要。
  • updateCredentials(Account, String, Bundle, Activity, AccountManagerCallback<Bundle>, Handler)
    • ユーザーに対して、新しいパスワードを入力してもらうよう依頼する。 対応する Authenticator がこのリクエストを処理する。
    • 保存されているパスワードを更新するため? 使いどころをあんまりわかってない。
    • API level 22 以下では MANAGE_ACCOUNTS パーミッションが必要。
  • getPreviousName
    • 指定のアカウントの前の名前を返す。
    • LOGIN_ACCOUNTS_CHANGED_ACTION ブロードキャストを受け取ったときに、アカウント名が変更されているかどうか検知できるようにするためのメソッドらしい。
  • Auth token 取得系 : AccountManager がキャッシュしていたらそれを返し、なければ対応する Authenticator が認証トークンを取得する。
    • getAuthToken(Account, String, Bundle, boolean, AccountManagerCallback<Bundle>, Handler)
      • バックグラウンドの処理向け。
      • 指定のアカウントの指定のトークン種別の認証トークンを取得する。 アカウントマネージャがキャッシュしている場合はそれが返される。 キャッシュされていない場合は authenticator がリクエストを処理する。
      • Authenticator は、パスワードが使えるのであればそれでサーバーに問い合わせを行う。 それが無理ならユーザーにログイン画面を表示して、ユーザー入力によって認証トークンを取得する。
      • notifyAuthFailure に真を渡したならば、そのインテントを開始するステータスバーの通知も表示される。
      • その場合 (ログインする必要がある場合? それともステータスバーの通知が表示される場合?) には、ユーザーが対応するまで何時間も、何日も、あるいは永遠に待つことになる可能性がある。
      • notifyAuthFailure に偽を渡した場合は、アプリケーションが Intent を開始する責任がある。
      • API level 22 以下では USE_CREDENTIALS パーミッションが必要。
    • getAuthToken(Account, String, boolean, AccountManagerCallback<Bundle>, Handler)
      • API level 14 で Deprecated になってるので Bundle パラメータ有り版を呼ぶこと。
    • getAuthToken(Account, String, Bundle, Activity, AccountManagerCallback<Bundle>, Handler)
      • フォアグラウンドで動いている処理向け。
      • 指定のアカウントの指定のトークン種別の認証トークンを取得する。 アカウントマネージャがキャッシュしている場合はそれが返される。 キャッシュされていない場合は authenticator がリクエストを処理する。
      • API level 22 以下では USE_CREDENTIALS パーミッションが必要。
    • blockingGetAuthToken
  • getAuthTokenByFeatures(String, String, String[], Activity, Bundle, Bundle, AccountManagerCallback<Bundle>, Handler)
    • 他のメソッド (getAccountsByTypeAndFeaturesgetAuthTokenaddAccount) の処理を組み合わせた便利メソッド。
    • API level 22 以下では MANAGE_ACCOUNTS パーミッションが必要。
  • invalidateAuthToken
  • hasFeatures
    • 指定のアカウントが指定の全ての機能を持っているかどうかを調べる。
    • 呼び出し側は GET_ACCOUNTS パーミッションを持っているか、もしくは Authenticator と同じシグネチャである必要がある。
自社アプリ (同じシグネチャを持つアプリ) のみ
  • removeAccount(Account, Activity, AccountManagerCallback<Bundle>, Handler)
    • アカウントマネージャからアカウントを削除する。 Authenticator は固有のポリシーによってアカウント削除をしないという選択をしてよい。
    • 呼び出し側は Authenticator アプリと同じシグネチャを持つ必要がある。
    • API level 22 以下では MANAGE_ACCOUNTS パーミッションが必要。
  • removeAccount(Account, AccountManagerCallback<Boolean>, Handler)
    • 上に同じ。 Deprecated。
  • renameAccount(Account, String, AccountManagerCallback<Account>, Handler)
    • 古いアカウントを削除し、古いアカウントのユーザーデータを持つ新しいアカウントを追加するのと同じ効果。 (Auth token はどうなるんだろ?)
    • 呼び出し側は Authenticator と同じシグネチャを持つ必要がある。
    • API level 22 以下では AUTHENTICATE_ACCOUNTS パーミッションと、authenticator と同じ UID である必要がある。
  • clearPassword
    • アカウントマネージャが保持しているパスワードを削除する。 「ログアウト」 ボタンの処理などで使われることを想定しているらしい。
    • setPassword メソッドでも同じことができるけどこっちの方が必要な権限は少ないっぽい。
    • アカウントの Authenticator と同じシグネチャが必要。
  • editProperties
    • Authenticator 固有の、Authenticator のプロパティ (アカウントごとではない) を編集する。 対応する Authenticator がこのリクエストを処理する? (未調査。)
    • 全ての Authenticator がこの機能を実装しなければならないわけではない。
    • Authenticator と同じシグネチャが必要。
    • API level 22 以下の場合は MANAGE_ACCOUNTS パーミッションが必要。

Authenticator (または、それに関連する処理) 向け

  • addAccountExplicitly(Account, String, Bundle)
    • アカウントをアカウントマネージャに追加する。
    • Authenticator に関連するサインアップ処理向け。
    • addAccount メソッドなどのシステムがアカウント追加を検知できるメソッド経由で呼ばれたわけじゃない場合は、自前で notifyAccountAuthenticated メソッドを呼ぶべき。
  • removeAccountExplicitly(Account)
    • アカウントをアカウントマネージャから削除する。
    • クライアント用のアカウント削除メソッドとは違い、Authenticator でのポリシー設定は見られないのだと思う。 (未調査。)
    • API level 22 以下では AUTHENTICATE_ACCOUNTS パーミッションと、さらに Authenticator と同じ UID である必要がある。
  • notifyAccountAuthenticated(Account)
    • アカウントが認証されたことをシステムに伝える。
    • このイベント情報が他のアプリで使われたりするっぽい? (未調査。)
    • 呼び出し側はアカウントの Authenticator と同じシグネチャを持つ必要がある。
  • getPassword
    • アカウントマネージャが保持しているパスワードを取得する。
    • 呼び出し側は Authenticator と同じシグネチャを持っている必要がある。
    • API level 22 以下では AUTHENTICATE_ACCOUNTS パーミッションが必要。
  • setPassword(Account, String)
    • アカウントマネージャにパスワードを保存する。 (あるいは削除する。)
    • Authentiator と同じシグネチャを持つ必要がある。
    • API level 22 以下では AUTHENTICATE_ACCOUNTS パーミッションと、さらに Authenticator と同じ UID である必要がある。
  • getUserData
  • setUserData(Account, String, String)
  • peekAuthToken(Account, String)
    • AccountManager のキャッシュから auth token を取得する。 なければ null が返される。
    • API level 22 以下では AUTHENTICATE_ACCOUNTS パーミッションが必要で、さらに Authenticator アプリの UID と同じ UID を持っている必要がある。
  • setAuthToken(Account, String, String)
    • Auth token をアカウントマネージャのキャッシュに追加する。
    • Authentiator と同じシグネチャを持つ必要がある。
    • API level 22 以下では AUTHENTICATE_ACCOUNTS パーミッションと、さらに Authenticator と同じ UID である必要がある。

その他

関連ページ

Hyper-V 上の Debian VM の vNIC の IP アドレスを管理 OS 側から取得できるように LIS を有効にする

Debian Hyper-V Windows 10 Windows PowerShell

表題通り。 Hyper-V 上の Debian 8.7.1 で Linux 統合サービス (Linux Integration Services; LIS) を有効にした方法のメモ。

私が試したのは、Windows 10 Pro (Insider Preview Build 14986) の Hyper-V 上の VMDebian 8.7.1 Jessie をインストールする Packer のビルドを実行しようとした、というもの。

前提

直面した状況

Packer でビルドして Hyper-V VMDebian 8.7.1 Jessie をインストールしようとしたところ、Packer がゲストマシンに SSH 接続しようとしてずっと待ち続けるという状況になった。 (下記表示のまま進まない。)

==> hyperv-iso: Waiting for SSH to become available...

Packer のログ ($env:PACKER_LOG=1 でログ出力されるようにした) を確認したところ、以下のようなメッセージが表示されていた。

2017/02/18 19:48:48 packer.exe: 2017/02/18 19:48:48 [DEBUG] Error getting SSH address: No ip address.

すなわち、管理 OS 側から仮想ネットワークアダプタの IP アドレスを取得できなかったぽい。

管理 OS 側から仮想ネットワークアダプタの IP アドレスを取得できなかった原因

「Error getting SSH address: No ip address.」 の原因を探したところ、以下の issue が引っかかった。 ここでゲスト OS 側が管理 OS に IP アドレスを伝える必要があるということを知った。

で、Linux ゲストの場合は、Linux 統合サービスが必要とのこと。

Debian 8.7.1 Jessie で LIS を有効にする

Debian 8 系では、LIS がディストリビューションに含まれている。

有効にするための手順がどこに書かれているのかわからなかったので困ったのだけれど、やってみたところ Debian 8.7.1 では、APT の hyperv-daemons パッケージをインストールして再起動するだけで LIS が有効になるっぽかった。 (実際に試して、管理 OS 側から IP アドレスを取得できることを確認した。)

apt-get install hyperv-daemons

今回の場合、Packer でビルドするために Preseed を使っていたので、preseed.cfg のパッケージ選択に hyperv-daemons を含めるようにした。

d-i pkgsel/include string openssh-server build-essential hyperv-daemons
    # これは一例です。 hyperv-daemons パッケージ以外のパッケージは必ずしも必要ではありません。

参考

  • Debian Jessie Hyper-V : Debian 8 で LIS を有効にする方法。 KVP、VSS、FCOPY 統合のために hyperv-daemons と 4.2 カーネルが必要とのこと。 KVP やら VSS やら FCOPY まで追いかけられていないが、参考にした。
  • Install Hyper-V (LIS) On Debian 8 : Debian 8 で LIS を有効にする方法。 こちらも参考にはしたが、ここに書かれている方法を全て実行する必要はなさそうだった。

読んだ : RESTful Web Services with Dropwizard / Alexandros Dallas 著

書籍 書評 ライブラリ JAX-RS JDBI Java

Dropwizard に関わる仕事をしているので読んでみました。

RESTful Web Services with Dropwizard

RESTful Web Services with Dropwizard

Dropwizard について

Dropwizard は Java の web アプリケーションフレームワークです。 基本的には既存ライブラリの組み合わせで web アプリケーションを構築するというもので、Dropwizard 固有の仕組みはさほど多くありません。 (例えば Web リクエストを受け取るのは Jersey で、DB アクセスには Hibernate か jDBI が使われる。)

特に Java EE 系の知識を持っている人であれば、とっつきやすい感じです。

本書について

本書は、Dropwizard を使って web アプリケーションを構築するための方法を説明するものです。 プロジェクトの準備や、HTTP リクエストを受けるエンドポイントの記述、DB アクセス、ユーザー認証、HTML を返す View テンプレートについてなど、基本的な要素について、サンプルコードを交えながら仕組みが解説されます。

Java EE などについてある程度わかっている人が読むと Dropwizard の公式ドキュメントを読むのと大差ないと思いますが、初心者の人が読むと結構わかりやすいんじゃないかなと思います。 (ある程度わかってる人にとっても、Dropwizard についてざっと知ることができて良いかもしれませんが、そういう使い方だとちょっと値段は高めに感じる気がします。)

本書での学び

参考のリンクとしては現時点での最新バージョンのドキュメントへのリンクです。 閲覧時の最新バージョンのドキュメントは各自探してください。

  • Dropwizard では、maven-shade プラグイン を使って、単体で web アプリケーションとして実行可能な JAR ファイル (uber-jar) を作る。
  • Hibernate Validator によるアプリケーション設定のバリデーションが可能。
  • jDBI で DB から取得した結果をオブジェクトにマップする方法として、@MapResultAsBean アノテーションを使うという方法もある。
    • 参考 : MapResultAsBean (jDBI 2.48.2 API)
    • とはいえ公式的なドキュメントは何もなく、ドキュメント化されていない挙動に依存することになるので不安。 (JDBI の機能の多くがドキュメント化されてないのでまあこれに限った話ではないのだけど。)
  • HTTP リクエストパラメータのバリデーション周り。
    • JAX-RS のリソースメソッドのパラメータのバリデーションを明示的に実行することも可能。 (@Valid アノテーションでのバリデーション実行しか知らなかった。)
    • 複数フィールドにまたがるバリデーション。
    • 参考 : Dropwizard Validation | Dropwizard
  • Dropwizard には HTTP クライアント用モジュールも含まれている。
  • 認証周り。
    • Basic 認証用のクラスが用意されている。
    • オプションの認証も可能。 (認証されたユーザーの場合はそのユーザー専用のコンテンツを表示し、さもなければ一般ユーザー向けのコンテンツを表示する、みたいな。)
    • CachingAuthenticator によるキャッシング。
    • 参考 : Dropwizard Authentication | Dropwizard
  • Fixtures for Easy Software Testing (FEST) というプロジェクトがある。 TestNGJUnit と一緒に使える。 ソフトウェアテストを書きやすくするライブラリ。

感想

Dropwizard をそこそこ使ってて公式ドキュメントも (全部ではないけど) 読んでいたので、本書での学びはあんまりなかったです。 とはいえ上に書いたように新たに知れたこともいくつかあったので読んでよかったです。 (そんなに時間もかけずにざっと読めましたし。)

とはいえ紙の本だと 30 ドル以上するので、ちょっと高い感じはしますね。