log4jの設定について。

Java/log4j

log4jの設定について。

log4jの設定ファイル(log4j.xmlとlog4j.propertiesがあるけどここではpropertiesについて。xmlについては適宜読み替えて下さい)の設定について。

log4jの基本的な使い方やpropertiesの基本的な書き方は他にちゃんと詳しくてこのブログのように胡散臭くないサイトさんやブログがあるのでそちらに譲るとして。今回は私の備忘録です。
今まであんまり真面目に勉強してこなくて、そのツケが回りに回って調査に一日かかった…orz

log4jの設定は、
・Category(Logger)
・Appender
・Layout
の3つからなる。
■Appenderは、出力情報の設定。
出力ログのファイルパスや、追加で出力するとか上書きするとかの設定や、日次でファイル変えていくだのそういった辺りを設定。
■Layoutは、Appenderにくっついていて、出力するログのレイアウト(日時出してログ出力クラス名出して、とかの出力される1行ログの書式)。
Appenderの下にいるのに、設定はこの3つからなる!てAppenderと肩並べてるのはAppender的に思うところもあるだろうなぁ。
■Categoryは、Javaのソースに記述されるログの設定名みたいなもの、と理解。
log4j.category.FOR_DEBUG=DEBUG, a1,a2
と書くと、"FOR_DEBUG"という名前のカテゴリのログレベルはDEBUGで、Appenderにはa1とa2を指定、という意味。
Appenderは複数指定可能。a1がコンソール出力、a2がファイル出力、という感じで区別すると良い。
Javaの方では、
Logger debugLogger = Logger.getLogger("FOR_DEBUG");
(なんかソース)
debugLogger.debug("でばっぐ");
という風に書く。

で、CategoryとLoggerの関係については分かったような情報が曖昧なような。
一応、LoggerはCategoryを継承しているので、実体としてはまぁ違いはないよ、と。
但し、Categoryは非推奨化していて、その内消え去る運命だということで、log4jのバージョンによって、CategoryとLoggerを使い分けないといけないとのことです。
この辺りから若干情報が怪しくなってくる(^^;)
ソースが教えてgooしかないとかそんなレベルです。まぁこの辺りはあまりまじめに調べてないのですすみません。。。
今回のアプリの設定ファイルではrootLogger宣言して、log4j.categoryを設定して、JavaではLoggerクラスを使ってる。この入り乱れてるのが普通なのか統一すべきなのかの判断が付かないのですが、今回は元が私が作ったアプリでないので、あまり大きな変更勝手に加えると怒られるので放置してます。
ネットって解決策は見つかることが多いけど、それが「普通」のやり方なのかを判断するのは難しいですヨネ。

話が逸れましたが。

で、category設定で少し悩んだのが、log4j.category[logger].xxxと記述するところの xxx 部分に、パッケージを書くんだ、と書いているサイトが多かったこと。
例えば、log4j.category[logger].com.foo.bar とか。すんごい適当ですが。
まず、誤解しそうになりますが、「パッケージを書く」というのは「書かなければいけない」ではないということ。
前述した例のように、適当な名前を付けてもOKです。
むしろこっちの方が分かりやすいような気も私はするんだけど…うーん。
利点は、パッケージのように、"."で繋げて書くと、設定の継承が使えるトコロ。
log4j.category[logger].com.foo.barは、log4j.category[logger].com.foo の設定を継承できます。
後は、例えばSQLを発行しているような共通部分のクラスのパッケージ名を書いてやって、レベルをDEBUGにしておくと、SQLがDEBUGログに出力されるとか。
で、Logger.getLogger()については、
・Logger.getLogger(String)
・Logger.getLogger(String, LoggerFactory)
の他に、
・Logger.getLogger(Class)
をというコンストラクタがあって、中でクラス名を取ってくれているのです。
具体的には Logger.getLogger(this.class); とか書いてやればOK。
これのお陰で、「パッケージを記述する」ってのが簡単に使えている、という背景もあるんだろうけれど。

後書いておきたいのが、ルートロガーとその他のカテゴリ(ロガー)の関係。
というか、ルートロガーに何が出力されるのかがもう分かんなくて分かんなくて。
(……でも書いてる内容間違ってるって!って場合は是非教えて頂ければ幸いです。)

まずカテゴリで設定されているログを、アプリログ、それ以外のクラス(例えばPreparedStatement.classとか)から出力されているログを、共通ログと定義します(名前が適切でないなどの突っ込みはご容赦下さい。。。)。

で、以下ルートロガーと各カテゴリとの関係。
(やっぱりルートカテゴリ-各カテゴリ、ルートロガー-各ロガー、って組み合わせにしないといけないような気がするなぁ…)

(1)アプリログはルートロガーで設定されているログレベルに関わらず、すべて出力される。但し、対象ログが各カテゴリで設定されているログレベルに満たなくて、各アプリログに出力されない場合はルートログにも出力されない。
(2)共通ログは、ルートロガーのログレベル以上の場合だけ出力される。
(3)log4j.properties に設定されていないカテゴリ名で出力されるログ
 例:Logger.getLogger("UNKNOWN");
 このUNKNOWNがlog4j.propertiesに設定されていない
…については、ルートロガーのログレベル以上の場合だけ出力される。

当然ながら、アプリログについては、各カテゴリで設定されているログレベル以上のログしか各Appenderには出力されない。

なので、開発環境→本番環境などで、ログレベル云々ではなく該当カテゴリに含まれるログすべてを出力したくない場合、そのカテゴリをコメントアウトしたり削除したりするのではなく、カテゴリに設定されているログレベルを上げることで対応すること。
そうでないと、出力先がないのでルートログに出力しておく、という判断になってすべてのログがルートログにでることになる(前述の通り、ルートロガーのログレベルにも依るけど)
まぁルートロガーを空にしておくと何も出ないんだけど。。。多分、出そうとして文字列の生成まではいくので、パフォーマンスに影響が出るような気がします。
ちゃんと調べてなくてアレですが。

まぁ、結論としては
log4j.category.FOR_DEBUG=DEBUG,a1
などの場合、
log4j.category.FOR_DEBUG=FATAL,a1
などにしてやると良い、ということです。なんか気持ちは悪いけども…

まとまりないですが、備忘録。
間違っていたらまた修正しにきます~

| | コメント (0) | トラックバック (0)

eclipse でjava classファイルの逆コンパイル

java / eclipse / 逆解析

まとめ。
eclipseで逆コンパイルをするにはJadclipseというプラグインを使用します。
他にも方法があるかもしれないですが、私はこれで上手くいったので他は調べてません。

必要なのは、Jadclipseのjarファイルと、実際動かすためのJad.exeの2つ。それぞれ以下から入手してください(2008.04.30.現在のアドレスです)

Jadclipse
http://jadclipse.sourceforge.net/wiki/index.php/Main_Page

jad.exe
http://www.kpdus.com/jad.html

ここで注意をしないといけないのは、Jadclipseのバージョンと、eclipseのバージョンを合わせておかないといけないということ。ずれていると設定しようとした時にエラーが発生してeclipseさんに怒られてしまいます。

で、まぁJadclipseはeclipseのpluginsフォルダに配置して、Jad.exeは…多分適当にどっかに配置して良いと思います。
私はeclipseフォルダの直下に配置しました。

その後、eclipseを起動して、
ウィンドウ > 設定 > Java > Jadclipse
 Path to decompiler というところに、Jad.exeを配置したアドレスを指定します。
 例)C:\test\eclipse\jad.exe
これでOK。eclipseのパッケージ・エクスプローラなどでclassファイルをダブルクリックすれば逆解析してくれます。

自分用備忘録として。

| | コメント (0) | トラックバック (0)

jdkとjreは何が違うのか。

…と思って検索したら非常に的確なお答えを書かれていました。

毎度のことながらお前そんなこと知らなかったのかというアレですがそこはそれ。

+++引用元:http://javafaq.jp/S000.html+++

>JRE と JDK はどう違うのですか?
>
>
>[S000 A-03]
>JRE, JDK はそれぞれ Java Runtime Environment, Java Development Kit の略で、
>前者は、JDK をベースに作られた Java のプログラムを実行する際に必要になる JVMと
>クラスライブラリのパッケージで、後者は、開発者向けのコンパイラなどのツールと
>クラスライブラリのパッケージです。
>Java 2以降では、JDKをSDK(Software Development Kit)と呼ぶようになりました。
>SDKにはJREが含まれているので、SDKを導入した開発者は別途JREを入手して導入する
>必要はありません。
>また、JRE は自分の作成したアプリケーションと共に再配布することが可能です。

…とのことでした。またひとつかしこくなった。

| | コメント (0) | トラックバック (0)

セッションに登録するObjectはSerializableでなければならない

Java/セッション/Serializable

自作クラスをセッションに登録している箇所で、偶然Exceptionが発生しているのを発見。
偶然、というのも、Exceptionが発生しているのが、どうやら『サーブレットコンテナが停止』するとき…今回だとTomcatを停止した時(厳密にはこの表現は違うのかな…最近こういうところで曖昧な知識しかない自分に気付いて凹)なので、わざわざログをチェックすることがなく、たまたまログに吐いてるSQLチェックしよーっと思って見たらException内容がダンプされていてΣ( ̄■ ̄)となった次第。

で、結論としてはセッションに登録するクラスはSerializableクラスをimplementしてないと駄目なんだぜ!ということらしいです。
こちらのページにとても分かりやすく纏められていたので御紹介。
ユーファームさん>コーディングの落とし穴>セッションに保存されるオブジェクトがシリアライズ可能でない
http://www.u-farm.jp/oto/srv_serialize.html
以下引用です。
======引用開始==============================================
【問題点】
セッションは画面遷移をまたいでオブジェクトを保存できる便利な「入れ物」ですが、基本的にメモリ領域の一部を割り当てて使っているため、 (1)割り当て領域が満杯になってしまったときや、(2)サーブレットコンテナを停止するときに、セッション上の保存オブジェクトをいったんDiskに書き出して退避させます。このようなオブジェクトのDisk書き出し処理をシリアライズといいます。 Javaではどんなオブジェクトもシリアライズできるわけではなくて、 java.io.Serializable を実装(implements)したクラスだけが対象となります。

Serializableを実装していないオブジェクトをセッションに保存した場合、最初のうちは問題ないかと思いますが、シリアライズが必要な局面でトラブルを起こします。(通常は NotSerializableException という例外を発生します。)
この問題は開発環境での一過性のテストでは発見しにくく、本番環境で連続稼動しているうちにトラブルの形で初めて発覚することが多いため、十分な注意が必要です。

======引用終了==============================================
解決方法も上記サイトに分かりやすく書かれていましたので御参照。
他の「落とし穴」は初心者さんには有用だな~と思われる内容で、逆説的にこれを知らなかった自分が初心者だということですね!orz

| | コメント (0) | トラックバック (0)

複数リソースファイル参照方法

Java+Struts+JSP

Strutsにおいて、JSPのタグには外部のメッセージリソースを
参照する機能があります。
で、これはリソースファイルが複数あってもOK。

(1)struts-config.xmlでの設定(※二つのファイルが存在する
場合)
<!-- ====== Message Resource 定義
================================ -->
<message-resources parameter="MessageResources"
key="message" />
<message-resources parameter="ApplicationResources"
key="application" />

(2)各JSPファイルで
<bean:message name="mess001" scope="request"
bundle="message" /><BR>

requestスコープに登録されているメッセージリソースファイ
ルに存在するmess001をキーとしたメッセージを表示する。

…スコープに登録、とかファイルに存在する、とか微妙な言葉
遣いが続きますね…(^^;)

| | コメント (0) | トラックバック (0)

javaのシステム情報取得(改行コードの取得について)

Windowsでの改行コードは、"\r\n" または "CR+LF"
UNIX機での改行コードは、"\n" または "LF"
Mac機での改行コードは、"\r" または "CR"

今回開発では、Windows XP + Tomcatで、本番環境は Linux + Tomcatでした。
Web上での表示のため、改行コードを<BR>タグに変換するシーンがあって、開発
時は、\r\n、または \n を<BR>に変換する、というロジックを組んでいたのです
が。
#\r\n、は private static final String NEW_LINE_CD = "\r\n"; のように定義

本番環境にソースをアップした時に、\マークがバックスラッシュではなくて本
当に\マークとしてしか扱われていないようで、改行コードがタグに変換されな
い事態が発生。
なんとか\マークをバックスラッシュに変換かけたいものの、Windows機上で記述
してアップしても意味がない。Windows機からUnix機にtelnetなどで接続して記
述しなおしてもダメ。
UNIX機上で修正すると、コンパイル時に文字化けが原因でコンパイルエラー…と
どないやねんな感じになっていたのですが、ひしだまさんのサイト
http://www.ne.jp/asahi/hishidama/home/tech/java/java.html
を見てあっさり解決。。。てことで、備忘録です。

private static final String NEW_LINE_CODE =
System.getProperty("line.separator");

Systemクラスかぁ……なるほどというか、元々知っていたのを忘れているのか知
らなかったのか…どちらにしてもダメな自分に脱力。
使用可能なプロパティ(主要なもののみ)はこんな感じ。

"file.separator" ファイルの区切り文字
"java.class.path" JavaのCLASSPATH
"java.class.version" Javaクラスのバージョン
"java.home" Javaがインストールされているディレクトリ
"java.vendor" Javaベンダー名
"java.vendor.url" JavaベンダーのURL
"java.version" Javaのバージョンナンバー
"line.separator" 行区切り文字
"os.name" オペレーティングシステムの名前
"os.version" オペレーティングシステムのバージョン
"path.separator" パスの区切り文字 (例) :
"user.dir" ユーザーの現在の作業ディレクトリ
"user.home" ユーザーのホームディレクトリ
"user.name" ユーザー名

詳しくはJavaでHello Worldさんのこのページを参照して下さい。
http://www.hellohiro.com/systemproperty.htm

| | コメント (0) | トラックバック (0)

iBatis:ページング機能

Java/iBatis

iBatis にはページング機能があるそうなー。

近々調べて追記したい。

とりあえず、

■DevGuide 41P参照

■http://d.hatena.ne.jp/akira_k/20040316/

| | コメント (1)

Struts マルチボックスのON/OFF制御について

Java/Struts/JSP

以下のように書くとOK。
<logic:iterate id="loopName" name="form" property="shohinList">
    <html:multibox property="shohinCd">
        <bean:write name="loopName" />
    </html:multibox>
    <bean:write name="loopName" />
</logic:iterate>

form はBeanで、shohinListとshohinCdは両方ともString配列の想定です。(一次元配列で表現できればStringじゃなくてCollection型ならなんでも良い…はず…)
shohinCd は一次元配列である必要があるけど、shohinList は二次元でも<bean:write name="loopName" property="XXX" />で表現できるはず。

検索で引っかかってきたサイトには、大体
>その "checked" 状態は、指定された値が内在するプロパティの
>現在地の配列の要素のうちの1つと一致するかどうかに基づいて、
>初期化されます。
て書いてあって、property と value に何を指定していいか具体的によくわからなかったのです。
基本は、shohinList に格納されている値(=loopName)でチェックボックスが複数生成されて、その値が、shohinCd の要素のどれかと同じだったら checked="true" となる。

| | コメント (0) | トラックバック (0)

log4jのjarのアリカ

Java/log4j 1.2.13

…これを公開すること自体羞恥プレイ…

log4jのzipファイルダウンロードした後、jarファイルを探すのに手間取ってしまったりしたので恥を忍んで覚書。
jarファイルはzipファイル解凍後のdist\libディレクトリ以下にいます。
それだけです。。。

| | コメント (0) | トラックバック (0)

JavaMailとEudoraの連携について

JavaMail/Eudora

業務でJavaMailを使用してJavaからのメール送信処理を実装している最中にぶち当たった分厚い壁について。
基本的にある程度のところまで調べたら満足する傾向があるので、情報として信用できるかと問われると自信がありません。常に覚書程度とゆーことで。

Windows+WebSphere+SqlServerというコンボで開発中。(問題とは関係ないと思われますが)
JavaMailでそのまま送信すると、勿論文字化けの恐れがあるためメール本文とSubjectを、MS932からISO-2022-JPにエンコードしてから送信。文末に文字化けする文字(~とか)が来たときの対処として、このエンコードメソッドの中で文末に改行コードを付加する、という処理を行っている。
例)あああ(MS932) →エンコード→ あああ(ISO-2022-JP)\r\n

秀丸メールなどでは問題がないが、上記のように改行コードを付加してエンコードを行ったSubjeectの内、文字数が少ないもの かつ Subject内で半角スペースが使用されていないもの について、eudoraで受信すると、ヘッダからSubjectそのものが消えてしまうという現象が発生しました。

原因としては、RFCではSubjectが改行された場合、慣例(?)として二行目は半角スペースを空けた上で始める、みたいな記述があるのですが、改行コードが付いているのにそもそも2行目がないこういったパターンはアウトなのかしら……
文字数が少ないもの、というのは文字数が多いと自動的に2行に切っているので、システムで切られた2行目は半角スペースで始まっています。それでも最終行にはエンコードメソッドで付けた改行コードがくっついていて、結局次の行はないのですが…eudoraがどういう変換をしているのかは謎。
結局、改行コードをくっつける、という処理を行わなければSubjectが消える事はないのですが、そうするとSubject末尾に文字化けする文字がくっついていると見事に文字化け。
Subject自体はエンドユーザが変更可能なため、覚えにくいデータ規則は余り作らない方がイイ。

結局、改行コードをくっつけた後、更に半角スペースを後ろにくっつけるという荒業で事を回避しました。
これを、eudoraのバグと言い切ってしまっていいものかは、メールの仕様自体に余り詳しくないので断定できません。。。
何かもっとすっきりとした根本的解決ってないものでしょうか。。。

あ、余談ですが、文字数が少なくてもSubject内に半角スペースが入っていれば、そこで2行に分かれるらしいので(英語でいうところの単語で行が分かれる?)、問題は発生しなくなります。なので、タイトル自体をシステムから生成するような仕様であれば、上手く間に半角スペースを入れ込むようにしてやれば問題ないです。

……問題自体が発生する確率が低いから、ネットでも余り話題になっていなくて苦労しました。。。

| | コメント (0) | トラックバック (0)

より以前の記事一覧

その他のカテゴリー

EXCEL | Flash | Java | JavaScript | oracle | perl | Shell | おすすめサイト | 小ネタ