画面エラーのログ出力を整理

今作っているJavaEEアプリですが、画面エラー発生時のログ出力を検討しました。ま、アプリケーションサーバであるWebLogicが勝手にログを出してくれますが、エラー以外にも勝手に出るので量が多くて見るのが辛いし、アプリとしては別途log4j2でロギングする方向にしているので、画面エラー発生時もlog4j出力に統一するという要件になります。WebLogicでlog4jとログを連携させるとかFilter使うとかいろいろやり方はありそうでしたが、画面個々に手を入れずに最も簡単なやり方は無いかなと考えたところ、画面エラー発生時はエラーページに遷移するようにしておいて、そのエラーページでログ出力させるという形にしてみます。

web.xml抜粋(今の所・・・)

エラーページ用JSF管理Bean

最後にweb.xmlで指定した/errors/index.xhtmlで、エラー内容は見せないように下記を忍ばせておけば、管理Beanのメソッドが実行されるという形になります。

要件はちゃんと確認しないと・・・VFSで作り直し

ちょっと前に書いたログファイルをダウンロードする機能ですが、実機となるLINUX上にデプロイすると動きませんでした。。。サーバへ接続はできているようなのですが瞬時に切断されているようです。原因切り分けの為、作業中に使っているユーザーIDで試してみると特に問題無く動いてます。TeraTermから指定のIDでログインしてみると即切断されたようになり、WinSCPでSFTPログインすると問題無くアクセスできます。
 で、要件を思い出すと、「SFTPはOK」ではなく、「SFTPのみOK」であった事に気が付きました。与えられたユーザーIDでは、SSH接続ができないセキュリティ設定になっていたという事なんです。(sshd_configでSFTP専用にされてました)
 要件上はたった2文字の違いですが、実装上は明らかに別物であり、SSHで接続するような実装ではNGという事になります。
 となるとGamynedのようにSSHを前提にしたライブラリでなく、SFTPのみでサーバへアクセスできるライブラリを探し、ApacheCommonsのVFSに落ち着きました。なお、VSFにはJschが必要みたいです。
 login,logoutはなさそうなんで、ManagedBeanの呼び出しメソッド引数にID、パスワード、ホスト名を追加して、SFTP処理クラスが殆どの変更箇所となります。とりあえず、ファイル受信は出来ましたので別途整理します。

bootstrapのdatepickerを使ってみる

前回、今作成中のWebLogicアプリにbootstrapを使う事にしたので、次は日付入力にdatepickerを使ってみることにしました。datepickerって、使う方も入力しやすいし、作る方も余計な日付チェック処理を作らなくて済むし、素晴らしいコンポーネントだと思います。昔はテキスト入力エリアを年/月/日と3個繋げて、日付妥当性やメンドクサイうるう年チェックとかしてたんですよ・・・
しかも、ダウンロードURLではオプション設定の書き方も教えてくれてます。
bootstrap-datepicker
JSF2画面xhtmlの該当箇所は下記ですが、そのままだとBean側が更新されないので、f:ajaxで通知してます。

画面メニューにbootstrapのnavbarを使ってみる

今作っているWebアプリですが、ログインユーザー権限によりメニューのリンク表示を切り替える要件の実装について、一緒に作ってるメンバーに聞いてみたら、bootstrapのnavbarがかっこいいとの事で使ってみました。
各画面で指定するテンプレートxhtmlにbootstrapのnavbarをセットする形です。なお、bootstrapのバージョンは少し古いですが2.3.2を使ってます。
bootstrapをダウンロードしたら、Webソース内のresourcesにダウンロードした各ディレクトリを入れ、メニューを表示する各画面xhtmlでは、下記のようにテンプレートを指定します。

テンプレートとして指定したmenu.xhtmlですが、その中の「SessionManager」はログイン情報を保持しているSessionScopedBeanで、ログイン時にログイン日時をlogintimeに、各権限の値をroleCdにセットし、xhtml側ではui:fragmentのrenderedで表示を切り替えます。

ログインした権限に従い下記のようにメニューを表示されます。
navbar

JSF2カスタムコンバータでデコードしつつdataTableの背景を変える

今作っているWEBアプリで、画面に一覧を表示して、一覧表示内の項目値によって背景色を変えたいという要件がありました。
で、JSF2のカスタムコンバータを使って、コード値を文言にデコードしつつ、裏でCSSクラスを変えることで背景色が動的に変わる形にしてみました。コンバータは一つで、どのコード体系でデコードするかは、attributeでコンバータに情報を渡す構成になってます、とりあえずは。。

CSS抜粋

xhtmlのdataTable部分抜粋
※wordsはwords.propertiesのファイル側に定義している項目タイトルの文言です

カスタムコンバータ

ManagedBean抜粋
※一覧表示対象のitemInfoの実装は割愛します。プロパティとゲッタ・セッタがあるだけです。。

こんな感じで表示できそうなので、別途整理して実装します。
上記例では色が変わるのは行でなくセル単位になります。なお、dataTableの場合、その中のoutputTextはdivに置き換えらえるようなので、コンバータではtdのスタイルを変えているのではなくdivが対象になってます。それをCSSでカバーしているのですが、CSSは得意でないので。。

ganymed ssh2を使ってダウンロード画面を作る

今作っているWebアプリケーションでサーバのログファイルをダウンロードしたいという要件があり、そこでganymedを使ってみることにしました。アプリケーションをデプロイしているサーバとは別に複数存在するサーバ上にあるログファイルを画面から選択してクリックでダウンロードという流れです。
 なお、サーバとログファイルが格納されているディレクトリ情報は別途DB等から取る形にして、下記はSFTPでファイルを取得する箇所の抜粋です。

POM.xml ganymed指定

画面に表示するログファイル情報

SFTP処理
※サーバは一般的なID・パスワード認証です。

画面処理
※HttpServletResponseのOutputStreamに直ファイルを突っ込むので、一時ファイルを置いたりしません。

xhtml
※ディレクトリリストの箇所は、上記ソース上割愛しています。
ディレクトリリストの左に置いたボタンクリックで、ファイル一覧を取得し、ファイル一覧のファイル名クリックでダウンロードします。

エラーハンドリングやサーバの切断、ファイルサイズの数値右寄せ等、細かい箇所がまだ出来ていませんが、とりあえず動きそうです。
最初、ログファイル情報のプロパティ名が先頭大文字とかだと、JSFでエラーになりちょっとハマりました。。

レルムの代わりにJASPICで

 今、企業内で少人数が使用するWEBアプリケーションをWebLogicで動かす前提で作ってますが、ユーザー認証についてどうしようかと要件を確認したところ、少人数使用のアプリなのでLDAP無し、WebLogicに登録・管理したくないのでWeblogicのレルムも使わないでとのこと。となると従来のDBにユーザーテーブル作ってユーザー管理画面とかも作る感じになります。
 ユーザーには数パターンあるうちの1つの権限を付与すれば使える画面と使えない画面が決まるので、基本的にURLで制御できる範囲です。で、いろいろ調べましたが、下記を参考にして、JASPIC(Java Authentication Service Provider Interface for Containers)というJavaEE7仕様に含まれているものを使ってみる事にしました。
http://arjan-tijms.omnifaces.org/2012/11/implementing-container-authentication.html
ここのSETP5にあるServerAuthModule実装のvalidateRequestに認証処理を書き込む形のようです。
下記のサンプルソースも参考になりました。
https://github.com/erik-wramner/YubikeyAuth/tree/master/yubi-jaspic-example

但し、WebLogicで動かす場合は、web.xmlにだけ設定すればよいだけでなく、weblogic.xmlにも同じような設定が必要みたいです。

web.xml

weblogic.xml

デプロイするとそのインスタンス全体に影響し、開発環境では管理サーバで動かしているので管理コンソールに入れなくなります。。

カテゴリー: Java

FilterでWeb要求・応答をログ出力してみる

今、リクエストを受信した後に対外接続を行うシステムを作ってますが、がつがつと外部に繋ぐのも気が引けるという事で、、そのシミュレータとして簡単なWebAPも作りました。
APサーバは、WebLogic11G。作っているAPの仕様上、POSTをサーブレット処理してます。
で、結局Oracleのページに乗っていたグッドなサンプルをそのままパクってみました(汗)
Oracle Containers for J2EE サーブレット開発者ガイド
Request処理は解るのですが、Responseの方はFilter内でラップするというちょっと自分では考え付かない内容でした。。
上記に載っている、FilterServletOutputStreamとGenericResponseWrapperは、深く考えずに同一パッケージ内にそのままクラスとして作ります。
で、Filterクラスを作ってログを出力します。よく使っているlog4j2でやってます。

で、web.xmlに上記Filterをセットします

最初サーブレットはアノテーション@WebServletで書きましたが、どうも11Gだとダメっぽいのでweb.xmlにservletをMappingする事にしました。シミュレータは本当に簡単なAPなので。。
開発環境は他のプロジェクトで使うWebLogic12cのままで11Gを別途用意しなかったんですが、実行環境が違うとデプロイに失敗して結構メンドクサイです。コンパイラーJavaのバージョンをちゃんと確認してなかったからなんですけど、、

WLSのデータソース設定せずにJPA

今筆者が作っているWEBアプリケーションのDB周り実装です。
インフラ的には、主にWLS12+OracleDBとなっていますが、社内特定部署に利用が限定されたアプリケーションなので、DBセッションは「節約したい」という微妙な要件です。さらに、WLSデータソース設定はしたくないとの希望です。
せっかくEE使うんで、JPA前提でやる事にしますが、WEBに出てる殆どのネタがWLSのデータソースを使っているんですよね。
セッションプールは別途OracleUCPの独自実装があるので、persistance.xmlで指定せずに、UCPのデータソースをプログラム上からエンティティマネージャに指定するというイメージなんですが、WEBで調べながら実際に動くまで結構時間掛かりました。。

まず、EclipseのプロジェクトファセットにJPAを追加するとpersistence.xmlが出来ますが、データソースをここでは設定しないのでエンティティクラス定義のみ書きます。

次にエンティティクラス(テーブル定義みたいなもの)

その次が、データアクセスインターフェース(データ操作定義)

さらに上記インターフェースをJPA実装したデータアクセスオブジェクト(DAO)

上記DAOのコンストラクタで読んでいるEntityManagerを取得するシングルトンクラス

上記を呼び出しているJava画面ソース

最後に上記呼び出し箇所のXHMLの抜粋

後で、テストしたところ、DB更新は出来ていてもクエリーでデータを取得すると反映していませんでした。永続化コンテキストからみの事象と思われますが、細かい仕様を調査するのは骨が折れるので、、、クエリー取得前にEntityManagerをclearする事で対処としました。

JAX-RSを使ってみる

今筆者が作っているサブシステムは、複数種類の定期ジョブとWeblogicで動作させる画面アプリと組合せなんですが、定期ジョブの実装方式として、JAX-RSを検討しました。

なんでジョブをJAX-RSで作るのか?という所なんですが、Weblogicデプロイモジュールに含めることでジョブ実行時のメモリ消費をインフラ設計範囲内に収める為(Coherenceキャッシュへのアクセスがある)と、ジョブ変更時のモジュール管理をサブシステムとして統一したいという理由です。

あと、ジョブ起動については既存のジョブ管理ツールに統一したいとの事なので、EJBスケジューリングは使えない前提です。というか、EJBスケジューリングの挙動検証がしきれてないので、お勧めするのを躊躇したという所なんですが。。

当然、そのままだと外部からアクセスできるので、セキュリティ対策としては要求元IPでフィルタする形で対応する事としてます。

簡単な汎用POSTリクエストモジュールを作成した後、JAX-RSとして動作する処理をJavaEEアプリ内に作成します。

Weblogicデフォルトではなぜか動かなかったので、
weblogic.jaxrs.server.portable.servlet.ServletContainerを使わず、
POMにjerseyを追加

web.xmlを上記に合わせる

JAX-RSソース(コンテキストルート/batch/JOB1のURLでPOST実行)

ジョブ管理の側はログファイルの検知をトリガーにするので、どのプロセスがログに書いたかはどうでもよく、これで行こうと思います

追伸 1年経って下記のような事もありました。。
weblogic.xmlのprefer-web-inf-classesをtrueにしたらハマった・・