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

TeraTermマクロでプロセスをKILL

UNIXサーバ作業の自動化として、特定のプロセスをKILLするマクロを書きました。
前提として
・停止対象のプロセスはJavaの常駐JOBが3つ
・プロセス停止前にチェック処理が必要
このチェック処理が複雑なので、マクロにしました。
下記は、サーバにログオンされた状態以降の抜粋です。チェック処理と最後のログオフは省略してます。
実際のツールはHTAで作業メニュー画面があり、画面操作でマクロを起動する構成にしました。

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のバージョンをちゃんと確認してなかったからなんですけど、、

TeraTermマクロのfileopenで失敗

去年作ったTeraTermマクロのサーバ作業の自動化ツールで1年以上問題無かった箇所でエラーになるとの事で見たら、端末のセキュリティレベルが変わっていてマクロのfileopenで失敗している事が判明。fileopenしているファイルが書き込めないように端末設定が変わっていたのが原因で、マクロのfileopenでは書き込めないとエラーになるんですね。
 で、マクロの仕様をネットで見たらfileopenの仕様に読み取り専用モードのオプションが4.85以降で追加されてるじゃないですか!
 かといって、ツールで使っているTeraTermマクロをバージョンアップするのも、20パターンくらいの作業を自動化しているのでちょっと躊躇。。
 作業自動化ツールをマクロで作ることにしたのは、基本ミドル・運用アプリ系の導入無し、複数サーバで同じような作業があるし、サーバ側に作業自動化シェルとか置くと、ここのサーバ運用的に変更の敷居が高いという環境上の要件からなんですが、マクロにしたらしたらで端末の設定変更でなくマクロを変えればいいじゃん的な発想に変わってしまうという、、まさにジレンマですね。変えやすいものは変われるけれど、それを維持するのは結構メンドクサイんです。。このメンドクサイという事実がシステムの開発・運用コストに直結しているハズなんですけどね。。

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する事で対処としました。

VBSでFTP

あるWindowsサーバのログファイルを別サーバへ定期的にFTP送信したいとの事で、VBSで簡単なスクリプトを作りました。これまでは、バッチやスクリプトでFTP用のコマンドファイルを作り、FTP -S:ファイル名で実行するような感じだったのですが、最近は、スクリプトだけでできるようです。
下記例は、D:\log\tempというディレクトリに一つのzipファイルが置かれており、そのファイルを送信するという前提です。
ちなみにzipファイル自体の名前でstrSrcを指定するとCopyHereが勝手にZipの中身を解凍した状態で送信されます。。そういや、CopyHereでzipの圧縮や解凍もできるからそういう事なんでしょうか。。恐るべしCopyHere

でも、このCopyHere、FTPでは非同期のようで送信終了タイミングが解らなくスリープ待ちせざるを得なかったり、上書き確認のダイアログがどうしても消せない等、ちょっとクセが強いです。。
今回の要件的にはまあ上書きの対処は見切りました。確実性が必要な処理だとこのやり方はしないかな~

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にしたらハマった・・

リファクタリング中にパニくる。。

現在、複数のアプリケーションを一人で同時作成しているのですが、ソースがぐちゃぐちゃになってきたので、今更ながら共通処理を別プロジェクトにまとめて一元管理する事にしました。
WebApのプロジェクトでは、ビルドパスの追加と、プロジェクトのプロパティ→Webデプロイメント・アッセンブリーで、共通処理プロジェクトを追加すればサーバ実行時に動くようになるようです。
 その後、ソースを共通処理プロジェクト側に移動させていたのですが、動作確認するとDB接続箇所で意味不明のエラーが発生し、接続できなくなってしまいました。

<2015/06/24 13時14分30秒 JST> <[ServletContext@25608288[app:OfficeAp module:officeap path:null spec-version:3.0]] Root cause of ServletException. javax.security.auth.message.AuthException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLException: ユニバーサル接続プールを起動できません: oracle.ucp.UniversalConnectionPoolException: データソースから接続を取得できません: java.sql.SQLException: 接続プロパティ: 書式エラー: Property is 'v$session.program' and value is 'XX.XXXX.XXX.XXXXXXXXXX.common.DBConnectionManager'

他にもいろいろソースを移動させていたので、何が原因か解らなくちょっとしたパニック状態。。
数時間試行錯誤した後、エラーメッセージをちゃんと見直してみる。
v$sessionのprogramにクラス名がセットできないみたいだけど。。なぜ?

結果、パッケージ名が長くなってセット出来なくなっただけでした。。
48文字までしかダメみたい。

カテゴリー: Java