システム開発で思うところ

JavaEEを主にシステム開発をしながら思うところをツラツラを綴る

思い付きのストック(WebFW)

自分向けの書き溜め(思いついたときに書き足す)。
いつになるか分からないけど、自分なりのJavaEEに薄いラッパーをつくるにあたって、やっておきたいこと。今のシステムのベースとして既に作り込んでいるものも含めて。既に実装しているものについても拡張性や交換可能性まで考慮は至っていないところばかりなので、その辺の見直しも含めた指針。
また、JavaEEがあると楽に環境が準備出来るけど、現状の私自身はTomcatを使っていることもあり、JavaEEに強依存した仕組みには極力したくないと思っている。

なぜ

JavaEEにしてもSpringにしても、セキュリティとかログとかインターセプターとか、なにかしらラップをするものが必要だと思ったから。また要件によって独自実装をする領域を基盤となるフレームワーク(JaveEEとかSpringBootとか)に挟んでおくことで、柔軟な拡張ポイントを確保することも出来るし、それが出来た方が良いと思う。 やりたいことは、すべてに対応するフレームワークというよりも、どこで何を拡張するのか分かりやすいフレームワーク
場合によっては、作業指針にとどまるケースもあると思っている。例えば、DB周りのツールとしてDomaを使う場合、Domaに依存させるのは、このレイヤーまでに留めて、ドメイン領域には浸食しないようにしましょう、みたいな。
考えているのは「書き換えを前提としているフレームワーク」とか「作法を規定するので中身はご自由に。一応、自分なりに便利だと思うコードは準備しておくけど、好きに書き換えてもらっていいですよ」というユルーイもの。つまり、オレオレフレームワークの雛形みたいなもの。

自分で動機を整理しつつ「こんなもの誰がいるのかな?」という思いはありつつ、自分自身が仕組みを作る中で試行錯誤した経緯を考えるとオープンなもので1つくらいあっても良いかなと改めて思ったので、とりあえず出来るだけやってみたいなと思う。*1

何を

共通部品

認証・認可

独自実装:あり
インターセプトで実装。現状はセッションのユーザー情報で保持している権限と、Controllerで指定した権限とのマッチングで制御している。
できればOAuth2みたいな感じで認証サーバーとの連携するようなサンプルまで出来たら素晴らしいんだろうな。

セキュリティ

独自実装:一部あり
CSRFXSSセッションハイジャック、といったところを仕組みとしてまとめたい。今はクローズドな環境で、更新をするユーザーが ごく限られているので、このあたりは後回しにしているけど、必ずほしい機能。

ログ

独自実装:あり
インタセプターによる自動ログ出力と、Producerによる実装をしてはいる。ただ、ログファイルの制御がいまいちちゃんと出来ていないとか問題が多い。。ログについては使用したいツールがシステムによって異なると思うので、そのあたりの置き換え容易性などを考慮した整理とあわせて、ちゃんと見直しをしたい。

例外

独自実装:あり
アプリケーション独自例外が、ログ出力とかメッセージ出力とかツールチップ制御とか、ごちゃごちゃになってしまっている。もっとスッキリできると思うので、ちゃんと見直しをしたい。もしくは、ドキュメントを整理して利用や改修をやり易いようにしておきたい。

バリデーション

独自実装:あり
メッセージの置き換えや、ツールチップの出力位置の情報共有については、自分なりに一旦は実装できたと思う。ただ、メッセージとバリデーションが密結合になっているので、そのあたりをもっと整理したい。
JSFのメッセージ出力とツールチップ出力と強依存の実装になっているところもある。ダメではないような気もするけど「パーフェクトJavaEEJavaEE」のCDI(2章)を読んだ印象では もうちょっと良い感じな整理が出来そうな気もしている。

国際化対応

独自実装:なし Resourceの汎用読み込みは実装済み。
propertiesを都度参照してメッセージを探すのではなくて、Enumで定数にしてパンチミスなどの発生させないようにしたい。 (propertiesからEnumAnnotationProcessorで生成する仕組みを検討中)

プレゼンテーション関連

メッセージツールチップ

独自実装:あり
例外時に限った実装になっている。例外とは分離させて、ツールチップ単体として完結したものにしたい。例外時には部品としてそれを使用するイメージ。

Ajaxによる更新

独自実装:あり
過去のブログは、現システムのエッセンスを抽出したものに近い。パッケージとして整理さえすれば良いだけかもしれない。

サブ画面制御

独自実装:なし

ダイアログとか子画面とか、そういう感じのもの。個人的には避けたい実装だけれど、実際の要件としては良く挙がっているネタなので。
PrimeFacesとかリッチコンポーネントもあるけれど、ここで試したいのは、サブウィンドウ。
参照サブウィンドウではなく、登録サブウィンドウ。 モーダル制御までするのであれば、それはHTML5とかPrimeFacesとかの出番なので、それは関与しない(ブラウザの挙動ではモーダルを保証できないという過去の経験より)。
この辺は、全くの無知なので、落としどころも含めて考察から必要。

モーダル画面連携

独自実装:なし

「サブウィンドウ」ではなくて、モーダルダイアログへの連携。クライアント側の実装については、各種クライアントフレームワークjQueryでゴリゴリとかやり方はたくさんあるので、そちらにお任せ。あくまで「連携」をするための仕組み、もしくは作法の整理。
この辺は、全くの無知なので、落としどころも含めて考察から必要。

ドメイン関連

カテゴリは設けたけど「POJO」であることがポイントになる気がするので、フレームワークとして設けないといけないことは、今のところ思いつかない。

永続化関連

DB操作

独自実装:あり

外部SQLファイルの参照について、独自に作り込んで「しまった」。このメモを整理している中で調べて見たら方法があったようだ。。

SQL文を外部ファイルに|老いぼれSEの艱難辛苦

ただ独自の実装といっても、指定のクラスパス内の指定クエリー名を読み込むだけのシンプルなもの。結局はNativeQueryで使用する文字列をどうやって渡すのか、というだけの話だから、これはこれで残しておいても良いかな、とも思う。それに上述のリンクは「NamedQuery」の話みたいだから「NativeQuery」でも同じかどうかは検証が必要になると思う。また、外部SQLファイルの検証を考えるとXML定義にしておくよりも平文SQLファイルの方が扱いやすい気がする。

現状の方式は、DBからNetBeansでEntityクラスを生成+基本となるクエリーは自動生成しておき、その他に必要な問い合わせをJPQLや外部SQLで作成をしている。Entityクラスの自動生成は色々な方法があるし、プロジェクトによってはExcelから自動生成をすることもあると思う。個人的にはDBからの取得結果のDTOとして充足していれば、それで良いと思っている。なので、ここでは、自動生成したEntityクラスに手を加えるのではない方式を整理できればと考えている。

少なくとも、今は自動生成したEntityクラスに問い合わせクエリーを記述したり、しなかったりと統一していないので、そこは見直したい。

また、これを言ったらどうしようもないんだけれど、永続化周りについては、DomaMyBatisDBFluteとか仕様としてのJPAすら適用外になることも多そうだし、SQL生成および外部SQLの読み込みそのものについても、採用する技術要素によって大きく変わってくると思う。

検討する指針としては「どのような技術要素でも、永続化においてドメイン領域と明確に分離する整理が出来ていること」「どのパッケージで、どういうことをするのか明確に整理すること」をポイントにしたいと思っている。なので、私が実装した外部SQLファイル読み込みの仕組みに強依存しない方が良いと思っている。

トランザクション制御

独自実装:あり

アプリケーションサーバー(Tomcat)のシステムのため、トランザクションEntityManagerを使って行っている。現状はEntityManagerに基本操作を加えたラップクラスを設けている。それはService層でEntityManagerを直接操作をするのを避けたいという考えから。
正直、トランザクション境界であれば、EEサーバーを使うことで、こんなことをしないでも良いと思う。 どちらかというと、ここで検討しておきたいのは、@Transactionalを直接使用しないことと、トランザクション境界をControllerの操作境界と同じようにログ出力などを同時にするようなインターセプターを実装することを想定している。
たとえば、EEサーバーとアプリケーションサーバーをそれぞれ分けて検討して、EEサーバーの場合、トランザクション境界は@Transactionalを使用することで解決しつつ、処理の前後のログについては独自に実装したインターセプターを作成する、とか。
まずはアプリケーションサーバー(JTAの実装を持っていないサーバー)から実装を作って、EEサーバーだと こんな風に書き換えたら良いと思いますよ、みたいな参照実装が作れたら良いなぁと思っている。

どのように(サンプル)

どんなものを作る?

フレームワークに限らず、道具は実際に自分が使ってみて嬉しいものであることが一番大事。そして、できればサンプルのためのサンプルではない方がさらに良い。
個人的な経験として、システム構築において1から作り込む手順を記すよりも、動く雛形システムがあって それを改造するのが一番楽だと思っている。

ということで「ユーザー登録」あたりが一番いいかなぁと思っている。 出来ればJavaEEでモノリシックなものと、Restなマイクロサービスっぽい感じの2パターンが作れたら良いかなぁ。
なんとなーく、この2つが出来たら、一見モノリシックなJavaEEな実装に見えるけど、フレームワーク部分が頑張る事で裏ではマイクロサービス風な仕組みが動いている、みたいなことが出来そうな気がしている。
一番の課題はトランザクション関連になると思っているし、そこについて問題が解消できるとは正直思っていないんだけど、なんとなーく構想だけはあるので、そこまで出来たら個人的には大満足。

パターンは?

同じユースケースでも、オペレーションは様々あると思っているし、いくつかのバリエーションを設けておくことで有用なサンプルになると思っている。

  • ショッピング風

SAStrutsの登録ユースケースのイメージ。入力→確認→完了、のパターン。
JavaScriptなどの無いシンプルなWebシステムらしい感じのパターン。

  • SPA

1画面でリアルタイム(またはSubmitで)登録するイメージ。問題は通信上の情報改竄を仕組みとしてどうやって回避できるのか、だと思う。「ショッピング風」は実際の登録情報はサーバー側に保持しているもので処理をするので、そのあたりの心配はないけれど、SPAの場合どうなるのか調べるところからになると思っている。
Restにおけるセキュリティと同じような課題になるかなぁと何となく考えているので、ここをちゃんと解消できたら色々と幅広い領域についても安心なものになる気がしている。

  • サブウィンドウ

登録用サブ画面を使うパターン。クラサバだとよく出てくるパターンと思っている。
SPAが出来たとしたら、このパターンも割と安全に実装できそうな気がしている。 あとは、親画面の方に良い感じに情報を連携できるのか?というところが課題になりそう。できるだけJavaScriptでリッチな実装をしないという風にしたい。

  • 一覧処理

新規登録ではなく、既存データの修正をする場合のパターンとして、一覧から直接部分的に修正をする。これもクラサバだとよくある気がする。

  • 大量処理

所謂、ファイルダウンロード&アップロードによる更新処理。個人的にCSV(カンマ区切り)は好きではなく、TSV(タブ区切り)の方を選びたい。ただ、それはそれで多くの人になじみがなさそうなので、見栄えの調整もしやすいExcel形式を考えている。
ここについてもポイントはファイル形式ではなくて、仕組みの方になるようにしたいと思っている。例えば「CSV形式にしたい場合は、ここの部分を変更したら良いんだな」と分かりやすいようなクラス分割をする、みたいな。

今回は会話型で対応しうる大量処理を前提にするに留めて、対応するのは同期・非同期の制御までは出来たら良いかなと思っている。

大量処理というと「バッチ」になると思う。ただそういうのはWebからトリガーするというだけでなく、タイマーとかコマンドで実行するフローになると思うので、今回の構想には入れないつもり。またバッチ処理については、自分の中でコレでいったん整理してみよう、という構想すら持ち合わせていないからという後ろ向きな理由もあったりしますが。。だからといってバッチを甘く見ているわけではなく、元バッチCOBOLerだった私としてはバッチ(分散処理・大量処理)の重要さは経験的に理解しているつもりではいます。むしろ、WebFWと混ぜてはいけないと思っていて、中途半端な整理はしたくないなぁと。まぁ言い訳ですね。

参考になるかな

Spring Boot で Boot した後に作る Web アプリケーション基盤/spring-boot-application-infrastructure // Speaker Deck

#jjug_ccc DDDとMicroservicesについて喋ってきましたー(∩´∀`)∩ - Mitsuyuki.Shiiba

GitHub - jkazama/ddd-java: Spring Boot + Java7 [ DDD Sample ]

*1:思うだけで終わる可能性も十分ありますが