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

PrimeFacesを試してみる - p:layout

PrimeFacesを試してみる - p:layout

PrimeFacesを研究しよう!と思い、PrimeFaces Showcaseをマネして作ってみようと思います。

開発環境については、環境構築編で書いたやつに追加していく感じです。

githubに公開しました

PrimeFaces Showcaseを作っていく

作っていくわけですが、まずはレイアウトを作ります。
showcaseを見てみると、こんな感じのレイアウトです。 f:id:clash_m45:20150510235553p:plain

showcaseのソースコードも公開されていて、どうやってサイドメニュー作ってるのかな~って見てみたんですが...

<h:body>

    <!-- PC CONTENT STARTS HERE-->
    <div class="PC">
        
    <div id="MENUSIDE">
        <div id="MENUSIDEindent">
            <span id="LOGO" class="bordersOfMenuSide">
                <h:graphicImage name="main/images/logo.svg" />
                <h:graphicImage id="BlueLogo" styleClass="hiddenLogo" name="main/images/logoBlue.svg" />
            </span>
  • showcase-5.2/resources/main/css/showcase.css
 /* menu side style*/
    #MENUSIDE{width:85px; float:left; background-color:#313b3f; border-right:solid 1px #151d21; overflow:hidden; width: 300px; position: fixed;}
        #MENUSIDEindent{width:100%; height:auto;}
            #LOGO{height:87px; display:block; padding:27px 0 5px 10px; z-index:997; background-color:#313b3f;margin-left:100px}
                #LOGO img{width:62px; height:auto; }

なーんか普通にCSSでゴリってる感じですわ。

CSSが苦手!!な私はほぼ全てJSFで作ってみようと思います。

p:layout と p:layoutunit

JSFでは画面のテンプレートを作ることが出来ます。
そのテンプレートのレイアウトにPrimeFacesのp:layoutを使っていきます。

3.62 Layout
Layout component features a highly customizable borderLayout model making it very easy to create complex layouts even if you’re not familiar with web design.

[google先生]
レイアウトコンポーネントは、することが非常に容易になり、高度なカスタマイズのBorderLayoutモデルを提供しています
あなたはWebデザインに慣れていない場合でも、複雑なレイアウトを作成します。

p:layoutの中にp:layoutunitを入れて、p:layoutunitのpositionに

  • north
  • south
  • west
  • east
  • center

を設定することで、こんな感じでレイアウト配置してくれるコンポーネントです。

f:id:clash_m45:20150511001224j:plain

  • 上の例のHTML
<p:layout fullPage="true">

    <p:layoutUnit position="north" size="100" header="Top" >
        <h:outputText value="North unit content." />
    </p:layoutUnit>
 
    <p:layoutUnit position="south" size="100" header="Bottom">
        <h:outputText value="South unit content." />
    </p:layoutUnit>
 
    <p:layoutUnit position="west" size="200" header="Left">
        <h:outputText value="West unit content." />
    </p:layoutUnit>
 
    <p:layoutUnit position="east" size="200" header="Right">
        <h:outputText value="Right unit content." />
    </p:layoutUnit>
 
    <p:layoutUnit position="center">
        //page code
    </p:layoutUnit>
 
</p:layout>

JSF Templateをp:layoutで作っていく

出来ました。

f:id:clash_m45:20150510235629p:plain

p:layoutはネストすることも出来ます。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head>
    <title><ui:insert name="title">Hello Java EE</ui:insert></title>
</h:head>

<h:body>
    <ui:debug hotkey="x"
        rendered="#{initParam['javax.faces.FACELETS_DEVELOPMENT']}" />

    <p:layout fullPage="true">

        <p:layoutUnit position="west" size="200" header="sidemenu">
            <ui:insert name="sidemenu">
                <!-- <ui:include src="header.xhtml"/> -->
                Side Menu area.
            </ui:insert>
        </p:layoutUnit>

        <p:layoutUnit position="center">
            <p:layout>
                <p:layoutUnit position="north" size="200" header="content header">
                    <ui:insert name="content-header">
                        Content Header area.
                    </ui:insert>
                </p:layoutUnit>

                <p:layoutUnit position="center" header="content">
                    <ui:insert name="content">
                        Content area.
                    </ui:insert>
                </p:layoutUnit>
            </p:layout>

        </p:layoutUnit>

    </p:layout>

</h:body>

</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<ui:composition template="/template/template.xhtml">
    <ui:define name="content">
        <h1>Hello World!!</h1>

        <h:outputLabel value="JSF world" />

        <p:spinner />
    </ui:define>
</ui:composition>
</html>

もしうまく動かなかったら、ブラウザのデバッグ機能で確認したり、あとは<h:body>とかがちゃんと使われてるかを確認して下さい。


p:layoutunitのオプションを説明

いろいろオプション属性を付けることでカッコよくなります。

resizable

レイアウトのサイズをマウスで変更出来る。

<p:layout>
    <p:layoutUnit position="north" size="200" header="content header" resizable="true" >

f:id:clash_m45:20150510235650p:plain

closable

レイアウトを閉じる。
でも閉じたら戻ってこない?

<p:layoutUnit position="west" size="200" header="sidemenu" closable="true" >

f:id:clash_m45:20150510235706p:plain

collapsible

レイアウトを畳む。 畳んだあと、開くボタンも出てきます。

<p:layoutUnit position="north" size="200" header="content header" collapsible="true" >

f:id:clash_m45:20150510235717p:plain

gutter

溝のサイズを指定するらしい。
なんかあんまりうまく動作してない・・・?

<p:layoutUnit position="center" header="content" gutter="0">

f:id:clash_m45:20150510235733p:plain

collapsed , collapseSize

collapsibleの状態を設定するものみたいです。
collapsed="true"だと最初から畳んだ状態で表示。
collapseSizeは閉じた時のサイズを指定する。

<p:layoutUnit position="north" size="200" header="content header" 
    collapsible="true" collapsed="true" collapseSize="100">

つーことで、templateが出来ました。
JSF templateはすごい使いやすくて、コンテンツのページはすごい記述が少なくて済むので嬉しくなります。

PrimeFacesのp:layoutCSSが苦手な私でもレイアウトが簡単に出来ました!

終わり。

PrimeFacesを試してみる - 環境構築編

PrimeFacesを試してみる - 環境構築編

githubに公開しました

環境:

1. プロジェクト作成

Gradleプロジェクトを作る。 f:id:clash_m45:20150510134912p:plain

gradle war pluginではweb系のファイルはsrc/main/webappに置くみたいなので、手動でソース・フォルダを作成します。
すると以下のようなフォルダ構成になります。

helloJavaEE
└─src
   ├─main
   │  ├─java
   │  ├─resources
   │  └─webapp
   │      └─WEB-INF
   └─test
       ├─java
       └─resources

2. build.gradle

gradleでJava EE構成したことなかったので、調べてみたらmaven repositoryはあるみたいっすね。

いらん記述を消して、以下build.gradleにしました。

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'war'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile(
        'commons-collections:commons-collections:3.2',
        'javax:javaee-api:7.0'
    )

    testCompile 'junit:junit:4.+'
}

3. index.xhtmlを作る

ここまででプロジェクトは出来たはずなので、index.xhtmlを書いてブラウザで表示してみます。

[新規] - [Web] - [HTMLファイル]でJSFテンプレート有りのxhtmlが作成できます。 f:id:clash_m45:20150510134918p:plain

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

<h:head>
    <title>Hello Java EE</title>
</h:head>
<h:body>

<h1>Hello World!!</h1>

<h:outputLabel value="JSF world" />

</h:body>
</html>

4. web.xmlを作る

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.faces</welcome-file>
    </welcome-file-list>
</web-app>

ファイル構成はこんな感じになりました。

helloJavaEE
└─src
    ├─main
    │  ├─java
    │  ├─resources
    │  └─webapp
    │      │  index.xhtml
    │      │
    │      └─WEB-INF
    │              web.xml
    │
    └─test
        ├─java
        └─resources

5. Glassfishへデプロイ!

動いた~

f:id:clash_m45:20150510135005p:plain

補足. gradleでglassfishにデプロイする

毎回gradle warしてglassfishにデプロイするの面倒だな~と思ったら出来ました。

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'war'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile(
        'commons-collections:commons-collections:3.2',
        'javax:javaee-api:7.0'
    )

    testCompile 'junit:junit:4.+'
}

ext {
    glassFishHome = 'C:/glassfish-4.1/glassfish4'
    asadmin = glassFishHome + (isWindows() ? '/bin/asadmin.bat'
                                           : '/bin/asadmin')
    domain = 'domain1'
}

def isWindows() {
    return System.properties['os.name'].toLowerCase().contains('windows')
}

task startServer(type: Exec) {
    commandLine asadmin, 'start-domain', '--debug=true', domain
}

task stopServer(type: Exec) {
    commandLine asadmin, 'stop-domain', domain
}

task deploy(type: Exec, dependsOn: 'war') {
    commandLine asadmin, 'deploy', '--force=true', war.archivePath
}

ほんで、eclipsegradle タスクビューを開いて、ポチポチっとするとデプロイ出来るようになりました。

f:id:clash_m45:20150510135019p:plain

デバッグeclipseの[デバッグの構成] - [リモートJavaアプリケーション]で実行できるようです。(まだ試してない)

6. Primefacesを試す

タイトルがPrimeFacesだったのを思い出しました。

build.gradleにPrimeFacesの依存関係を追加します。

dependencies {
    compile(
        'commons-collections:commons-collections:3.2',
        'javax:javaee-api:7.0',
        'org.primefaces:primefaces:5.2'
    )

    testCompile 'junit:junit:4.+'
}

試す!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<h:head>
    <title>Hello Java EE</title>
</h:head>
<h:body>

<h1>Hello World!!</h1>

<h:outputLabel value="JSF world" />

<p:spinner />

</h:body>
</html>

どや~ f:id:clash_m45:20150510135034p:plain

JenkinsでFEST-Swingを実行する

FEST-SwingはJava Swingのテストフレームワークです。
FEST-Swing

Seleniumっぽい感じでSwingをテスト出来るフレームワークです。

で、これをJenkinsでCIしたいわけですが、Seleniumと同じようにウィンドウが必要になります。
いろいろやって、上手く動くところまで出来たので、ここに残しておきます。

Windowsの場合

FESTのドキュメントにあるんだけど、なんかようわからんってことで、以下方法で出来たのでとりあえずはこれでよかった。

  • 単純にJenkinsが動いてるサーバにログインし続ける。

ただしログアウトしたらテストが失敗するので、常に開いた状態じゃないとだめ。
StackOverFlowあたりで「セキュリティについては気にすんなw」みたいな英語の回答があったw

Linux/Debian などの場合

今回はDebian系のOSでやってたんだけど、とても簡単に出来ることがわかった。

まずすごく参考になったのが、この記事
JenkinsでFEST-Swing - やざわラボブログ この方法はたぶんGUI無しのときのやり方と思う。

Debian派生のOSでGUI有りでインストールしていろいろして出来たので以下に書く。

Debian GUIでインストールした時の話

まずGUI有りの場合に何も設定しないで実行すると、FESTが「X11変数(DISPLAY)が設定がされていません」的なエラーで失敗します。
ここは素直にDISPLAY環境変数に設定してあげましょう。

ちなみに私の環境だとコンソールでecho $DISPLAYしたら:0.0と出ました。
なんで設定されてるのにうまく動かんのじゃとは思ったけど、EnvInject Pluginという環境変数をJOBごとに設定できるプラグインで設定してあげた。

ちょっとJenkinsが手元には無いので、この画像のProperties Contentに、DISPLAY=:0.0と設定したら動いた!!! Properties Content


ということで、Swingアプリって今あんまり作ってる人いないのかもしれないけど、レガシーなアプリをCIしたい時とかに参考になればと思います。

JavaFXで作り直させてくれぇぇぇぇぇぇぇ!!!!!!

おわり

GradleでマルチプロジェクトのJUnit ReportとJacoco Reportを出す

Gradleのマルチプロジェクトを使う必要があって、だいぶハマったので記事に残しておこうと思う。

マルチプロジェクト構成

  • root
    • myproject
    • myproject-test

ここでは、実際のディレクトリとしてフラットに存在する例

$ ls
myproject  myproject-test  root

root

親プロジェクト。 最初はsettings.gradleしか持っていない状態。

settings.gradle

includeFlat "myproject", "myproject-test"

includeで階層型になる。参考

myproject

プロダクトコードプロジェクト。 ここにもJUnitテストコードがあったりする。

myproject-test

myprojectプロジェクトのテスト用プロジェクト。 単体・結合・総合テスト用JUnitが置かれたりする。

現状の問題点

このままgradle test jacocoTestReportしたら、myproject・myproject-testのbuildにそれぞれレポートが出力される。

  • root
  • myproject
    • build
      • jacoco - test.exec
      • reports
        • jacoco - html - index.html
        • tests - index.html
  • myproject-test
    • build
      • jacoco - test.exec
      • reports
        • jacoco - html - index.html
        • tests - index.html

これだとJenkinsで管理するときにレポートが上手く行かなくて困る。

myprojectとmyproject-testのJUnit,Jacocoレポートを一括、まとめて、統合、結合でレポートしたい!

JUnit Report

23.13. テスト - gradle userguide
-> 例23.14 Creating a unit test report for subprojects

ここに書いてあるんだけど、なんでか英語のまま!(激怒)

root/build.gradle

subprojects {
    apply plugin: 'java'

    test {
        // 別タスクで一括で出力する
        reports.html.enabled = false
    }
}

task testReport(type: TestReport) {
    destinationDir = file("$buildDir/reports/allTests")
    reportOn subprojects.tasks.test
}

はまりどころは、apply plugin: 'java'が必須というところ。 これはGradleの知識がまだ不足してたからだけど、rootからsubprojectを見た時に定義されてないとダメポ

myprojectとかmyproject-testでapply plugin: 'java'してるからrootではいらないかな?

とかいうのが落とし穴でした。

結果レポート出力

ということで、rootにtestReportというTaskを追加したので、実行する。

$ cd root

$ gradle clean test testReport
:myproject:clean
:myproject-test:clean
:myproject:compileJava
:myproject:processResources UP-TO-DATE
:myproject:classes
:myproject:compileTestJava
:myproject:processTestResources UP-TO-DATE
:myproject:testClasses
:myproject:test
:myproject-test:compileJava
:myproject-test:processResources UP-TO-DATE
:myproject-test:classes
:myproject-test:compileTestJava
:myproject-test:processTestResources UP-TO-DATE
:myproject-test:testClasses
:myproject-test:test
:testReport

BUILD SUCCESSFUL

Total time: 19.366 secs
  • root
    • build
      • reports
        • allTests - index.html
  • myproject
  • myproject-test

myprojectmyproject-testにはreportsは出力されてない。OK

f:id:clash_m45:20150124161734p:plain

Jacoco Report

お次はJacoco Reportをまとめて出力します。
maven時代はcovertura使ってたんだけどなんだか最近はjacocoがいいのかな?ってことでこちらを使ってます。

このGithub Gistを参考にしました。
Aggregated Jacoco reports in a multi-project Gradle build

あとは公式説明書
Chapter 34. The JaCoCo Plugin

DSLも見ないと全然わかりません。
DSL - JacocoReport

Projectのプロパティも使うので、DSL見ます。
DSL - Project

root/build.gradle

allprojects {
    apply plugin: 'java'
    apply plugin: 'jacoco'

    repositories {
        jcenter()
    }
}

subprojects {
    test {
        // 別タスクで一括で出力する
        reports.html.enabled = false

        jacoco {
            //execをrootprojectに出力する
            destinationFile = file("$rootProject.buildDir/jacoco/${project.name}.exec")
        }
    }
}

task testReport(type: TestReport) {
    destinationDir = file("$buildDir/reports/allTests")
    reportOn subprojects.tasks.test
}

task jacocoRootReport(type: JacocoReport) {
    dependsOn = subprojects.test
    //レポート対象はmyprojectのソース
    additionalSourceDirs = files(project('myproject').sourceSets.main.allSource.srcDirs)
    sourceDirectories = files(project('myproject').sourceSets.main.allSource.srcDirs)
    classDirectories = files(project('myproject').sourceSets.main.output)
    //レポートのためのexecはjacocoTestReportタスクの設定を利用
    executionData = files(subprojects.tasks.jacocoTestReport.executionData)
    reports {
        html.enabled = true
        xml.enabled = false
        csv.enabled = false
    }
}
  • ハマリポイント
    • rootprojectにもjacoco pluginが必要
      • jacocoRootReportタスクでjacocoのクラスパスを要求されるので、plugin applyしておかないと怒られます。
    • カバレッジ対象はmyprojectのソースにしたい
      • projectのプロパティの使い方がいまいちよくわからないのが問題で、かなりはまった。
    • jacoco execをrootprojectに出したい
      • ハマった原因はやっぱりprojectのプロパティがよくわからなかったから。

結果レポート出力

結果がわかりやすいようにJavaファイルを変更しました。

それではタスク実行。

$ cd root

$ gradle clean jacocoRootReport
:clean
:myproject:clean
:myproject-test:clean
:myproject:compileJava
:myproject:processResources UP-TO-DATE
:myproject:classes
:myproject:compileTestJava
:myproject:processTestResources UP-TO-DATE
:myproject:testClasses
:myproject:test
:myproject-test:compileJava
:myproject-test:processResources UP-TO-DATE
:myproject-test:classes
:myproject-test:compileTestJava
:myproject-test:processTestResources UP-TO-DATE
:myproject-test:testClasses
:myproject-test:test
:jacocoRootReport

BUILD SUCCESSFUL

Total time: 21.308 secs
  • root
    • build
      • jacoco
        • myproject-test.exec
        • myproject.exec
      • reports
        • jacoco - jacocoRootReport - html - index.html

f:id:clash_m45:20150124161706p:plain

myprojectのソースだけがカバレッジ対象になってます!


なんつーか一番はまりやすいのはprojectのプロパティの使い方だなーとかなり思ってます。
略式記法がわかりづらすぎる・・・

はてなダイアリーからブログに移行しました。

Atom Editor Markdown Perview の フォントについて(Windows)

AtomWindowsにも対応したので、早速メインエディタとして使ってみてます。

で、気づいたんですが、最初から入ってるMarkdown Previewの漢字表示が中国語っぽくね?って話です。
海外製のエディタでよくある、漢字が中国語フォントだーってやつですね。

ってことでフォントを指定してあげていい感じにしたいと思います。


Markdown Previewのフォントを変える

Markdown Previewのパッケージ内にあるlessを変更します。

○Markdown Previewのフォルダを開く
設定画面(Ctrl + ,)を開き、
1. "makrdown"と入力し、パッケージを検索する。
2. [Open to Atom]をクリックすると、パッケージのフォルダがAtomで開く。


○lessファイルのfont-familyにフォントを追加
1. stylesheets -> markdown-preview.less を開く。
2. 3行目に"font-family"があるので、そこに好きな日本語フォントを追加する。
3. パッケージを読み込み直す。(Ctrl + Alt + r)

変更前

@font-family: "Helvetica Neue", Helvetica, sans-serif;


変更後

@font-family: Consolas, Meiryo, "Helvetica Neue", Helvetica, sans-serif;

私は最近Consolasという等幅フォントが好きなので、それにしています。
Consolasは日本語フォントが無いので、後ろにメイリオを付けてます。


以上、簡単ですがMarkdown Previewのフォント変更でした。

    • -

仕事用にmajestouch 赤軸使ってから家のキーボード(Microsoft)が打ちづらーてしゃーない......
あとhetenaがmarkdownに対応ってブログのほうだけなんすね。辛い

vagrant windows環境でSSH for Teraterm

最近流行りのchef soloを入門するべく、『入門Chef Solo - Infrastructure as Code』を購入して絶賛入門中です。

で、chef soloを試すためのVM環境をセットアップするために、
vagrantを使って、Cent OSを入れてみました。
# 本では4章で解説

で、vagrant sshssh接続できるはずなんですが、windows環境だとssh無いよ!ということで失敗します。
こんな感じで。

>vagrant ssh
`vagrant ssh` isn't available on the Windows platform. You are still able
to SSH into the virtual machine if you get a Windows SSH client (such as
PuTTY). The authentication information is shown below:

Host: 127.0.0.1
Port: 2222
Username: vagrant
Private key: C:/Users/hogehoge/.vagrant.d/insecure_private_key

そんで、ggった結果puttyだとかcygwinだとか、いくつかヒットするものの
正直・・・めんどくせぇ・・・・です。


あれ?sshしたいだけならTeratermでいいんじゃね?

vagrantの設定ファイル(Vagrantfile)をchef solo入門通りにいじったなら、

config.vm.network :hostonly, "192.168.50.2"

みたいな記述があるはずです。
これが作った仮想サーバのIPなので、teratermで接続して、
アカウントは id / pass : vagrant / vagrant です。

これでいいじゃん!


別にアフェってるわけでもないのに載せちゃう

まだvagrantでゲストOS作るしかしてないから、もしかしてchef-soloがssh必須だったらダメですね(^q^)

ログ出力 "したい" 時と "したくない" 時を実装

log4jでログ出力してて、例えばコンソールアプリケーションを作ってる時に、
あるアプリではコンソール+ログファイル両方出力したいけど、
もう一方のアプリではコンソールには出さなくて、ログファイルにだけ出したい、ってときがある。

そしてその2つのアプリは同じロジックを呼ぶ、つまり呼ばれるロジックはログを出力する時としない時がある。
うーん、log4jの標準機能ではクラス単位での切替くらいしかできないよなー、ってことで、こんな感じにしたらできたのでご紹介。
# もっとCoolにできるなら教えてください。


clashm45/log4j_mute · GitHub

MyLoggerクラスを作って、

public class MyLogger {
  private Logger logger = null;
  private static final String NoConsole = "NoConsole";
  
  private MyLogger(Class<?> clazz){
    logger = Logger.getLogger(clazz.getName());
  }

  private MyLogger(String prefix, Class<?> clazz){
    logger = Logger.getLogger(prefix+"."+clazz.getName());
  }

  public static MyLogger getInstans(Class<?> clazz){
    return new MyLogger(clazz);
  }

  public static MyLogger getInstansNoConsole(Class<?> clazz){
    return new MyLogger(NoConsole, clazz);
  }

  public void info(String msg){
    logger.info(msg);
  }
~~~
}

log4j.xml でこうする

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

  <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out" />
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d %5p %c - %m%n" />
    </layout>
  </appender>

  <appender name="file" class="org.apache.log4j.FileAppender">
    <param name="File" value="target/App.log" />
    <param name="Append" value="true"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d %5p %c - %m%n" />
    </layout>
  </appender>

  <category name="log4j_mute">
    <priority value="info"/>
    <appender-ref ref="stdout"/>
    <appender-ref ref="file"/>
  </category>

  <category name="NoConsole">
    <priority value="info"/>
    <appender-ref ref="file"/>
  </category>

</log4j:configuration>

こんなロジッククラスを作る。
LogicA

public class LogicA {
  private static MyLogger logger = MyLogger.getInstans(LogicA.class);
  public static void process(){
    logger.info("処理A!!");
  }
}

LogicB

public class LogicB {
  private static MyLogger logger = MyLogger.getInstans(LogicB.class);
  public static void process(){
    logger.info("処理B!!");
  }

  public static void mute(){
    logger = MyLogger.getInstansNoConsole(LogicB.class);
  }
}

そしてロジックを利用するアプリケーションでこんな風にする。

public class App{
  public static void main( String[] args ) {
    LogicA.process();
    LogicB.process();
    LogicB.mute();
    LogicB.process();
  }
}

処理結果:コンソール

$ java -cp "src/main/resources;target/log4j_mute-1.0-SNAPSHOT-jar-with-dependencies.jar" log4j_mute.App
2012-12-18 14:39:29,461 INFO log4j_mute.LogicA - 処理A!!
2012-12-18 14:39:29,462 INFO log4j_mute.LogicB - 処理B!!

処理結果:ログファイル

$ cat target/App.log
2012-12-18 14:39:29,461 INFO log4j_mute.LogicA - 処理A!!
2012-12-18 14:39:29,462 INFO log4j_mute.LogicB - 処理B!!
2012-12-18 14:39:29,463 INFO NoConsole.log4j_mute.LogicB - 処理B!!

カテゴリを使ってログ出力方法を変えてるわけです。