Arquillianチュートリアルを埋め込みWeldでテスト走らせるところまでやってみる
TweetPosted on Friday Jan 24, 2014 at 05:02PM in Technology
JavaEEで結合テストを楽にするツール/フレームワークのArquillianを使ってみます。基本的にはオフィシャルのチュートリアル[2][4]をなぞるだけです。ここでは埋め込みWeld使ったテストが緑色になるところまでやります。
環境
- Eclipse Kepler SR1
- Apache Maven 2.2.1 (r801777; 2009-08-07 04:16:01+0900)
- Apple JDK6u65
- OS X 10.9.1
準備
プロジェクトを作る
kyle-no-MacBook:arquillian kyle$ mvn archetype:generate -DarchetypeGroupId=net.avh4.mvn.archetype -DarchetypeArtifactId=java-1.6-archetype
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO] task-segment: [archetype:generate] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Preparing archetype:generate
[INFO] No goals needed for project - skipping
[INFO] [archetype:generate {execution: default-cli}]
[INFO] Generating project in Interactive mode
[INFO] Archetype [net.avh4.mvn.archetype:java-1.6-archetype:0.0.3] found in catalog remote
Define value for property 'groupId': : org.arquillian.example
Define value for property 'artifactId': : arquillian-tutorial
Define value for property 'version': 1.0-SNAPSHOT:
Define value for property 'package': org.arquillian.example:
Confirm properties configuration:
groupId: org.arquillian.example
artifactId: arquillian-tutorial
version: 1.0-SNAPSHOT
package: org.arquillian.example
Y:
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: java-1.6-archetype:0.0.3
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: org.arquillian.example
[INFO] Parameter: artifactId, Value: arquillian-tutorial
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: org.arquillian.example
[INFO] Parameter: packageInPathFormat, Value: org/arquillian/example
[INFO] Parameter: package, Value: org.arquillian.example
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: groupId, Value: org.arquillian.example
[INFO] Parameter: artifactId, Value: arquillian-tutorial
[INFO] project created from Archetype in dir: /Users/kyle/tmp/arquillian/arquillian-tutorial
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 25 seconds
[INFO] Finished at: Fri Jan 24 20:48:27 JST 2014
[INFO] Final Memory: 23M/310M
[INFO] ------------------------------------------------------------------------
kyle-no-MacBook:arquillian kyle$
プロジェクトが出来ました
kyle-no-MacBook:arquillian kyle$ ls -l total 0 drwxr-xr-x+ 8 kyle staff 272 1 24 20:48 arquillian-tutorial kyle-no-MacBook:arquillian kyle$
pom.xmlを書き換える
JavaEE6用の依存性を追加します。結果以下のように。本当はJavaEE7でやりたいのですが何かとらぶるのもいやなのでとりあえずチュートリアル通りに。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.arquillian.example</groupId>
<artifactId>arquillian-tutorial</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>arquillian-tutorial</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-integration</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>net.avh4.util</groupId>
<artifactId>imagecomparison</artifactId>
<version>0.0.2</version>
<scope>test</scope>
</dependency>
<!-- clip -->
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-6.0</artifactId>
<version>1.0.0.Final</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
<!-- clip -->
</dependencies>
</project>
Eclipseで開く
FileからImportを開く

Existing Maven Projectsを選択

作ったプロジェクトのディレクトリを選択してFinish

特にエラーもなくプロジェクトができました
Java6が探し出されてしまったのがアレですがとりあえず我慢
pom.xmlを編集する
Maven Surefire Pluginはオプションだけど入れとくのをお勧めするとか書いてあるので、とりあえずこれも追加。動かすコンテナはとりあえずWeld EE Embeddedになっている。最終的にはスタンドアロンで動いてるWildFlyにしたいんだけどまあとりあえず。結果こうなる。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.arquillian.example</groupId>
<artifactId>arquillian-tutorial</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>arquillian-tutorial</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>1.1.2.Final</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-integration</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>net.avh4.util</groupId>
<artifactId>imagecomparison</artifactId>
<version>0.0.2</version>
<scope>test</scope>
</dependency>
<!-- clip -->
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-6.0</artifactId>
<version>1.0.0.Final</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
<!-- clip -->
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<scope>test</scope>
</dependency>
<!-- for weld ee embedded start -->
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-weld-ee-embedded-1.1</artifactId>
<version>1.0.0.CR3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<version>1.1.5.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.4</version>
<scope>test</scope>
</dependency>
<!-- for weld ee embedded end -->
</dependencies>
</project>
クラスを作る
package org.arquillian.example;
import java.io.PrintStream;
/**
* A component for creating personal greetings.
*/
public class Greeter {
public void greet(PrintStream to, String name) {
to.println(createGreeting(name));
}
public String createGreeting(String name) {
return "Hello, " + name + "!";
}
}
テストクラスを作る
package org.arquillian.example;
import javax.inject.Inject;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.Assert;
import org.junit.runner.RunWith;
@RunWith(Arquillian.class)
public class GreeterTest {
@Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap.create(JavaArchive.class)
.addClass(Greeter.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Inject
Greeter greeter;
@Test
public void should_create_greeting() {
Assert.assertEquals("Hello, Earthling!",
greeter.createGreeting("Earthling"));
greeter.greet(System.out, "Earthling");
}
}
クラスとテストクラスの配置

Maven Dependenciesの下にあるjarファイルを数えてみると72個あります。
テスト実行
テストクラスのウインドウで右クリック、Run As→JUnit Test

コンソールへの出力

JUnit窓への出力

やっと@Inject使ったコードが動くとこまできました。準備は大変だったけど、埋め込みコンテナだけにテストの実行速度は普通のJavaクラスの単体テスト並の早さ。長くなったので続きは別の項で。
続き
Arquillianチュートリアルの埋め込みGlassFish3でテストを走らせるところをやってみる
参考文献
Tags: test
jQuery File Uploadとサーブレットでファイルアップロード画面を作ってみる
TweetPosted on Friday Jan 24, 2014 at 09:13AM in Technology
jQuery File UploadとJava Servletを使ってドラッグアンドドロップで複数ファイルのアップロードが可能な画面を作ってみます。
ここでは[1]を使います。[3]が参考になりそうです。サーバ側での受け取りはサーブレットを使います。Servlet3のAPIを使って作ります。
環境
- jQuery-File-Upload-9.5.3
- WildFly 8.0.0CR1
- Oracle JDK7u51
- OS X 10.9.1
準備
- [1]からzipファイルをダウンロードしてきます。私は9.5.3.zipというファイルを取ってきました
- この要領でEclipseでJavaEE7プロジェクトを作ります
作る
画面側でHTMLファイル以外に必要なもの
- jQuery本体
- js/jquery.fileupload.js
- js/jquery.iframe-transport.js
- js/vendor/jquery.ui.widget.js
jQuery本体はCDNから取ってきます。下3つはjQuery-File-Uploadのzipファイルに含まれていますので適当な場所にコピーします。この例ではjsディレクトリを作ってそこにまとめて置きました。
プロジェクトの構造
こんな感じ

画面側
index.html
- 基本はファイル選択ボタンを押してファイルダイアログ出して選択
- 直接ブラウザの画面へドラッグアンドドロップも可
- 複数ファイルOK
- 簡単なプログレスバー的なものあり
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>jQuery File Upload Example</title>
<style>
.bar {
height: 18px;
background: green;
}
</style>
</head>
<body>
<input id="fileupload" type="file" name="files[]" data-url="upload" multiple>
<div id="progress">
<div class="bar" style="width: 0%;"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="js/jquery.ui.widget.js"></script>
<script src="js/jquery.iframe-transport.js"></script>
<script src="js/jquery.fileupload.js"></script>
<script>
$('#fileupload').fileupload({
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .bar').css(
'width',
progress + '%'
);
}
});
</script>
</body>
</html>
バックエンド側
UploadReceiveServlet
package jqueryfileul;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@WebServlet("/upload")
@MultipartConfig(fileSizeThreshold = 1024 * 1024, maxFileSize = 1024 * 1024 * 5, maxRequestSize = 1024 * 1024 * 5 * 5)
public class UploadReceiveServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
for (Part part : request.getParts()) {
System.out.println(part.getName());
System.out.println(part.getContentType());
System.out.println(part.getSubmittedFileName());
System.out.println(part.getSize());
if ("text/plain".equals(part.getContentType())) {
try (InputStream is = part.getInputStream();
InputStreamReader r = new InputStreamReader(is);
BufferedReader br = new BufferedReader(r)) {
System.out.println(br.readLine());
}
}
}
}
}
動かしてみる
画面はこんな感じ

ドラッグアンドドロップ
わかりにくいけどFinderからファイル2個ドラッグしてるところです。

プログレスバーが緑色に

サーバ側でも取れてますね

その他
日本語ファイル名が化ける
私の環境だと何故か日本語ファイル名でアップロードすると文字化けが起こります。この設定しとけば大丈夫だろうと思っていたのだけど。またそのうち調べる。クライアント側でファイル名をURIエンコードしないといけないのかな。
PrimeFacesのファイルアップロードコンポーネントお勧め
JSFの動くWebコンテナがあるならPrimeFacesの同機能[7]を使うのがお勧めです。何故わざわざこんな風に書いているかというと[6]の問題にはまったらしく、advancedモードで動かす事が出来なかったからです。
ちなみにPrimeFacesの同コンポーネントはかつてCommons FileUploadとCommons IOに依存していて、なおかつフィルタの設定も必要だったのですが、JSF2.2上で動かすなら両者とも不要になったようです。WildFlyでは動かなかったけど。GlassFish4なら動くのかな。
参考文献
- jQuery File Upload Demo
- 7 Javascript Ajax File Upload Plugins
- Java Servlet – jQuery File Upload (multiple, drag&drop, progress…) | HMKCode
- Basic plugin · blueimp/jQuery-File-Upload Wiki
- JSF 2.2 で待ちに待ったFileUploadを試す - DENのシステムエンジニアの思うこと
- [WFLY-2329] File upload doesn't work - JBoss Issue Tracker
- PrimeFaces - ShowCase
Tags: web
ロガーを設定してみる
TweetPosted on Thursday Jan 23, 2014 at 04:32PM in Technology
環境
- WildFly8.0.0CR1
jboss-cliからやる方法
CLIの管理コマンドjboss-cliを起動しconnectした後に打つコマンドです
コンソールのログレベルをTRACEレベルにする
/subsystem=logging/console-handler=CONSOLE:change-log-level(level=TRACE)
org.hibernate.SQLのロガーをTRACEレベルで作る
/subsystem=logging/logger=org.hibernate.SQL:add(level=TRACE)
この2つをやると取り急ぎHibernateのSQLが出るようになります。
コマンドを打つとすぐに設定が反映されてログが出るようになります。再起動はいりません。便利だ。
コンソールのログレベルを確認
/subsystem=logging/console-handler=CONSOLE:read-resource
追加したロガーを確認
/subsystem=logging/logger=org.hibernate.SQL:read-resource
ロガーを削除
/subsystem=logging/logger=org.hibernate.SQL:remove
ロガーを一覧表示
ls /subsystem=logging/logger
ロガーのログレベルを変更
org.hibernate.SQLのログレベルをTRACEに変更
/subsystem=logging/logger=org.hibernate.SQL:change-log-level(level=TRACE)
ファイルハンドラの設定
- ここからはWildFly8.0.0Finalで実験。多分CR1でも同じだと思うけど
ログ出力用サーブレット
- こんな感じのログ出力サーブレットをデプロイして実験してみる
package logger;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/")
public class LogServlet extends HttpServlet {
private static final java.util.logging.Logger JUL_LOGGER1 = java.util.logging.Logger.getLogger("hoge.logger1");
private static final org.slf4j.Logger SLF4J_LOGGER1 = org.slf4j.LoggerFactory.getLogger("hoge.logger1");
private static final java.util.logging.Logger JUL_LOGGER2 = java.util.logging.Logger.getLogger("hoge.logger2");
private static final org.slf4j.Logger SLF4J_LOGGER2 = org.slf4j.LoggerFactory.getLogger("hoge.logger2");
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
JUL_LOGGER1.info("JUL_LOGGER1.info()");
SLF4J_LOGGER1.info("SLF4J_LOGGER1.info()");
JUL_LOGGER2.info("JUL_LOGGER2.info()");
SLF4J_LOGGER2.info("SLF4J_LOGGER2.info()");
}
}
設定
- jboss-cliを使う
ファイルハンドラ作成
/subsystem=logging/file-handler=HOGE_LOGGER1:add(level=INFO, file={"relative-to"=>"jboss.server.log.dir", "path"=>"HOGE_LOGGER1.log"}, append=true, autoflush=true)
ロガーをファイルハンドラを指定して作成
/subsystem=logging/logger=hoge.logger1:add(use-parent-handlers=false,handlers=["HOGE_LOGGER1"])
この状態でサーブレットにアクセスすると
kyle-no-MacBook:log kyle$ pwd /Users/kyle/apps/wildfly-8.0.0.Final/standalone/log kyle-no-MacBook:log kyle$ cat HOGE_LOGGER1.log 08:30:31,672 INFO [hoge.logger1] (default task-11) JUL_LOGGER1.info() 08:30:31,672 INFO [hoge.logger1] (default task-11) SLF4J_LOGGER1.info() kyle-no-MacBook:log kyle$
- この例だとEclipseのコンソールやserver.logには出なくなる。hoge.logger2の出力だけ残る:
08:30:31,672 INFO [hoge.logger2] (default task-11) JUL_LOGGER2.info() 08:30:31,673 INFO [hoge.logger2] (default task-11) SLF4J_LOGGER2.info()
- ハンドラには、他にも日時でローテートできるファイルハンドラや、サイズでローテートできるファイルハンドラ、syslogに転送するハンドラなどがある[3]
- logbackほど豊富ではないが、ほとんどの局面で問題なさそうな品揃えな気はする
server.logには出したくないけどコンソールには出したい
- こうするとコンソールに出るようになる
/subsystem=logging/logger=hoge.logger1:assign-handler(name=CONSOLE)
- コンソールの出力
08:40:33,090 INFO [hoge.logger1] (default task-14) JUL_LOGGER1.info() 08:40:33,090 INFO [hoge.logger1] (default task-14) SLF4J_LOGGER1.info() 08:40:33,090 INFO [hoge.logger2] (default task-14) JUL_LOGGER2.info() 08:40:33,091 INFO [hoge.logger2] (default task-14) SLF4J_LOGGER2.info()
- HOGE_LOGGER1.log
08:40:33,090 INFO [hoge.logger1] (default task-14) JUL_LOGGER1.info() 08:40:33,090 INFO [hoge.logger1] (default task-14) SLF4J_LOGGER1.info()
- server.log
2014-03-06 08:40:33,090 INFO [hoge.logger2] (default task-14) JUL_LOGGER2.info() 2014-03-06 08:40:33,091 INFO [hoge.logger2] (default task-14) SLF4J_LOGGER2.info()
日時でローテートさせたい
- periodic-rotating-file-handlerを使うとできる
- server.log用にデフォルトで作られているハンドラの設定はこんな感じになっている
[standalone@localhost:9990 /] /subsystem=logging/periodic-rotating-file-handler=FILE:read-resource
{
"outcome" => "success",
"result" => {
"append" => true,
"autoflush" => true,
"enabled" => true,
"encoding" => undefined,
"file" => {
"relative-to" => "jboss.server.log.dir",
"path" => "server.log"
},
"filter" => undefined,
"filter-spec" => undefined,
"formatter" => "%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n",
"level" => "ALL",
"name" => "FILE",
"named-formatter" => "PATTERN",
"suffix" => ".yyyy-MM-dd"
}
}
- 上を参考に分単位でローテートするファイルハンドラを作ってみる
/subsystem=logging/periodic-rotating-file-handler=HOGE_LOGGER2:add( \
append=true, \
autoflush=true, \
enabled=true, \
file= {"relative-to"=>"jboss.server.log.dir", "path"=>"HOGE_LOGGER2.log"}, \
formatter= "%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n", \
level=INFO, \
named-formatter=PATTERN, \
suffix=".yyyy-MM-dd_HHmm")
- hoge.logger2ロガーを作る
- HOGE_LOGGER2とCONSOLEをハンドラにする
/subsystem=logging/logger=hoge.logger2:add(use-parent-handlers=false,handlers=["HOGE_LOGGER2", "CONSOLE"])
- こんな感じになる
kyle-no-MacBook:log kyle$ ls -l HOGE_LOGGER2* -rw-r--r--+ 1 kyle staff 164 3 6 09:01 HOGE_LOGGER2.log -rw-r--r--+ 1 kyle staff 0 3 6 08:54 HOGE_LOGGER2.log.2014-03-06_0854 -rw-r--r--+ 1 kyle staff 822 3 6 08:58 HOGE_LOGGER2.log.2014-03-06_0858 -rw-r--r--+ 1 kyle staff 328 3 6 08:59 HOGE_LOGGER2.log.2014-03-06_0859 kyle-no-MacBook:log kyle$ cat HOGE_LOGGER2.log.2014-03-06_0858 2014-03-06 08:58:15,099 INFO [hoge.logger2] (default task-15) JUL_LOGGER2.info() 2014-03-06 08:58:15,101 INFO [hoge.logger2] (default task-15) SLF4J_LOGGER2.info() 2014-03-06 08:58:18,526 INFO [hoge.logger2] (default task-1) JUL_LOGGER2.info() 2014-03-06 08:58:18,526 INFO [hoge.logger2] (default task-1) SLF4J_LOGGER2.info() 2014-03-06 08:58:19,645 INFO [hoge.logger2] (default task-2) JUL_LOGGER2.info() 2014-03-06 08:58:19,645 INFO [hoge.logger2] (default task-2) SLF4J_LOGGER2.info() 2014-03-06 08:58:20,461 INFO [hoge.logger2] (default task-3) JUL_LOGGER2.info() 2014-03-06 08:58:20,461 INFO [hoge.logger2] (default task-3) SLF4J_LOGGER2.info() 2014-03-06 08:58:22,126 INFO [hoge.logger2] (default task-4) JUL_LOGGER2.info() 2014-03-06 08:58:22,127 INFO [hoge.logger2] (default task-4) SLF4J_LOGGER2.info() kyle-no-MacBook:log kyle$ cat HOGE_LOGGER2.log.2014-03-06_0859 2014-03-06 08:59:03,932 INFO [hoge.logger2] (default task-5) JUL_LOGGER2.info() 2014-03-06 08:59:03,933 INFO [hoge.logger2] (default task-5) SLF4J_LOGGER2.info() 2014-03-06 08:59:04,258 INFO [hoge.logger2] (default task-6) JUL_LOGGER2.info() 2014-03-06 08:59:04,258 INFO [hoge.logger2] (default task-6) SLF4J_LOGGER2.info() kyle-no-MacBook:log kyle$ cat HOGE_LOGGER2.log 2014-03-06 09:01:39,835 INFO [hoge.logger2] (default task-7) JUL_LOGGER2.info() 2014-03-06 09:01:39,836 INFO [hoge.logger2] (default task-7) SLF4J_LOGGER2.info() kyle-no-MacBook:log kyle$
ファイルサイズでローテートさせたい
- size-rotating-file-handlerを使えば可能
- 保持する古いログの上限を設定すると、上限を超えた古いログを自動で削除してくれる
- ハンドラの作成はこんな感じ。サイズ2Kでローテート、5つを超えたら削除
/subsystem=logging/size-rotating-file-handler=SRFH1:add( \
append=true, \
autoflush=true, \
enabled=true, \
file= {"relative-to"=>"jboss.server.log.dir", "path"=>"SRFH1.log"}, \
formatter= "%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n", \
level=INFO, \
named-formatter=PATTERN, \
rotate-size="2k", \
max-backup-index="5" )
- hoge.logger1にアサインする
/subsystem=logging/logger=hoge.logger1:assign-handler(name=SRFH1)
- さっきのサーブレットのリロードをしばし連打するとこんな感じになる
kyle-no-MacBook:log kyle$ pwd /Users/kyle/apps/wildfly-8.0.0.Final/standalone/log kyle-no-MacBook:log kyle$ ls -l SRFH* -rw-r--r--+ 1 kyle staff 746 3 6 10:44 SRFH1.log -rw-r--r--+ 1 kyle staff 2056 3 6 10:44 SRFH1.log.1 kyle-no-MacBook:log kyle$ cat SRFH1.log.1 2014-03-06 10:44:18,330 INFO [hoge.logger1] (default task-15) JUL_LOGGER1.info() 2014-03-06 10:44:18,330 INFO [hoge.logger1] (default task-15) SLF4J_LOGGER1.info() 2014-03-06 10:44:22,966 INFO [hoge.logger1] (default task-1) JUL_LOGGER1.info() 2014-03-06 10:44:22,967 INFO [hoge.logger1] (default task-1) SLF4J_LOGGER1.info() 2014-03-06 10:44:23,132 INFO [hoge.logger1] (default task-2) JUL_LOGGER1.info() 2014-03-06 10:44:23,133 INFO [hoge.logger1] (default task-2) SLF4J_LOGGER1.info() 2014-03-06 10:44:23,268 INFO [hoge.logger1] (default task-3) JUL_LOGGER1.info() 2014-03-06 10:44:23,268 INFO [hoge.logger1] (default task-3) SLF4J_LOGGER1.info() 2014-03-06 10:44:23,391 INFO [hoge.logger1] (default task-4) JUL_LOGGER1.info() 2014-03-06 10:44:23,392 INFO [hoge.logger1] (default task-4) SLF4J_LOGGER1.info() 2014-03-06 10:44:25,137 INFO [hoge.logger1] (default task-5) JUL_LOGGER1.info() 2014-03-06 10:44:25,138 INFO [hoge.logger1] (default task-5) SLF4J_LOGGER1.info() 2014-03-06 10:44:25,315 INFO [hoge.logger1] (default task-6) JUL_LOGGER1.info() 2014-03-06 10:44:25,316 INFO [hoge.logger1] (default task-6) SLF4J_LOGGER1.info() 2014-03-06 10:44:25,451 INFO [hoge.logger1] (default task-7) JUL_LOGGER1.info() 2014-03-06 10:44:25,451 INFO [hoge.logger1] (default task-7) SLF4J_LOGGER1.info() 2014-03-06 10:44:25,574 INFO [hoge.logger1] (default task-8) JUL_LOGGER1.info() 2014-03-06 10:44:25,574 INFO [hoge.logger1] (default task-8) SLF4J_LOGGER1.info() 2014-03-06 10:44:26,623 INFO [hoge.logger1] (default task-9) JUL_LOGGER1.info() 2014-03-06 10:44:26,623 INFO [hoge.logger1] (default task-9) SLF4J_LOGGER1.info() 2014-03-06 10:44:26,767 INFO [hoge.logger1] (default task-10) JUL_LOGGER1.info() 2014-03-06 10:44:26,767 INFO [hoge.logger1] (default task-10) SLF4J_LOGGER1.info() 2014-03-06 10:44:26,901 INFO [hoge.logger1] (default task-11) JUL_LOGGER1.info() 2014-03-06 10:44:26,902 INFO [hoge.logger1] (default task-11) SLF4J_LOGGER1.info() 2014-03-06 10:44:27,048 INFO [hoge.logger1] (default task-12) JUL_LOGGER1.info() kyle-no-MacBook:log kyle$ cat SRFH1.log 2014-03-06 10:44:27,048 INFO [hoge.logger1] (default task-12) SLF4J_LOGGER1.info() 2014-03-06 10:44:27,184 INFO [hoge.logger1] (default task-13) JUL_LOGGER1.info() 2014-03-06 10:44:27,185 INFO [hoge.logger1] (default task-13) SLF4J_LOGGER1.info() 2014-03-06 10:44:27,306 INFO [hoge.logger1] (default task-14) JUL_LOGGER1.info() 2014-03-06 10:44:27,307 INFO [hoge.logger1] (default task-14) SLF4J_LOGGER1.info() 2014-03-06 10:44:27,452 INFO [hoge.logger1] (default task-15) JUL_LOGGER1.info() 2014-03-06 10:44:27,453 INFO [hoge.logger1] (default task-15) SLF4J_LOGGER1.info() 2014-03-06 10:44:27,599 INFO [hoge.logger1] (default task-1) JUL_LOGGER1.info() 2014-03-06 10:44:27,599 INFO [hoge.logger1] (default task-1) SLF4J_LOGGER1.info() kyle-no-MacBook:log kyle$
- さらに連打するとこうなる
kyle-no-MacBook:log kyle$ ls -l SRFH* -rw-r--r--+ 1 kyle staff 1652 3 6 10:46 SRFH1.log -rw-r--r--+ 1 kyle staff 2058 3 6 10:46 SRFH1.log.1 -rw-r--r--+ 1 kyle staff 2056 3 6 10:46 SRFH1.log.2 -rw-r--r--+ 1 kyle staff 2061 3 6 10:46 SRFH1.log.3 -rw-r--r--+ 1 kyle staff 2061 3 6 10:46 SRFH1.log.4 -rw-r--r--+ 1 kyle staff 2063 3 6 10:46 SRFH1.log.5 kyle-no-MacBook:log kyle$ head SRFH1.log.5 2014-03-06 10:46:17,340 INFO [hoge.logger1] (default task-7) SLF4J_LOGGER1.info() 2014-03-06 10:46:17,516 INFO [hoge.logger1] (default task-8) JUL_LOGGER1.info() 2014-03-06 10:46:17,517 INFO [hoge.logger1] (default task-8) SLF4J_LOGGER1.info() 2014-03-06 10:46:17,653 INFO [hoge.logger1] (default task-9) JUL_LOGGER1.info() 2014-03-06 10:46:17,653 INFO [hoge.logger1] (default task-9) SLF4J_LOGGER1.info() 2014-03-06 10:46:17,789 INFO [hoge.logger1] (default task-10) JUL_LOGGER1.info() 2014-03-06 10:46:17,789 INFO [hoge.logger1] (default task-10) SLF4J_LOGGER1.info() 2014-03-06 10:46:17,952 INFO [hoge.logger1] (default task-11) JUL_LOGGER1.info() 2014-03-06 10:46:17,952 INFO [hoge.logger1] (default task-11) SLF4J_LOGGER1.info() 2014-03-06 10:46:18,085 INFO [hoge.logger1] (default task-12) JUL_LOGGER1.info() kyle-no-MacBook:log kyle$
- java.util.loggingちっくな感じ。ちゃんと古いのは消えている
- 書いてから気づいたけどnamed-formatterとformatterはどっちかだけでいいかも
syslogにログを飛ばしてみる
- OS Xは10.9.2
- TCPにも出来るかもしれないけどとりあえずUDPでやってみる
OS Xのsyslogdの設定
- ソケット経由でログの送信を受け付けるようにする
- syslogdのplistの編集
kyle-no-MacBook:LaunchDaemons kyle$ sudo /usr/libexec/PlistBuddy /System/Library/LaunchDaemons/com.apple.syslogd.plist Command: add :Sockets:NetworkListener dict Command: add :Sockets:NetworkListener:SockServiceName string syslog Command: add :Sockets:NetworkListener:SockType string dgram Command: save Saving... Command: quit
- syslog.confに適当なテスト用facilityを追加
local1.* /var/log/hoge1.log
- syslogdの再起動
kyle-no-MacBook:LaunchDaemons kyle$ sudo launchctl unload com.apple.syslogd.plist kyle-no-MacBook:LaunchDaemons kyle$ sudo launchctl load com.apple.syslogd.plist kyle-no-MacBook:LaunchDaemons kyle$ sudo lsof -i:514 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME launchd 1 root 39u IPv4 0xf0749ee857f40f93 0t0 UDP *:syslog launchd 1 root 147u IPv6 0xf0749ee836545ceb 0t0 UDP *:syslog syslogd 56930 root 4u IPv4 0xf0749ee857f40f93 0t0 UDP *:syslog syslogd 56930 root 5u IPv6 0xf0749ee836545ceb 0t0 UDP *:syslog kyle-no-MacBook:LaunchDaemons kyle$
- loggerからログを出してみる。ソケット経由で送る方法はわからんかった
kyle-no-MacBook:etc kyle$ logger -p local1.notice hogehoge kyle-no-MacBook:etc kyle$ cat /var/log/hoge1.log Mar 6 11:19:24 kyle-no-MacBook.local kyle[57062]: hogehoge kyle-no-MacBook:etc kyle$
WildFly側の設定
- まずハンドラを作る
- [6]に若干説明がある
- facilityはsyslog.confの書き方と若干異なる。一覧は[6]にある
- hostnameってのはログの送信元ホスト名らしい
- server-addressが送信先ホスト名
/subsystem=logging/syslog-handler=SYSLOG1:add( \ app-name="hogeapp", \ facility="local-use-1", \ hostname="kyle-wildfly", \ level=INFO, \ server-address="localhost")
- hoge.logger1にアサイン
/subsystem=logging/logger=hoge.logger1:assign-handler(name=SYSLOG1)
- サーブレットをリロードすると
kyle-no-MacBook:log kyle$ tail -f /var/log/hoge1.log Mar 6 11:19:24 kyle-no-MacBook.local kyle[57062]: hogehoge Mar 6 11:29:15 1 2014-03-06T11: 29:15.653+09:00 kyle-wildfly hogeapp 5435 hoge.logger1 - JUL_LOGGER1.info() Mar 6 11:29:15 1 2014-03-06T11: 29:15.670+09:00 kyle-wildfly hogeapp 5435 hoge.logger1 - SLF4J_LOGGER1.info() Mar 6 11:30:03 1 2014-03-06T11: 30:03.549+09:00 kyle-wildfly hogeapp 5435 hoge.logger1 - JUL_LOGGER1.info() Mar 6 11:30:03 1 2014-03-06T11: 30:03.549+09:00 kyle-wildfly hogeapp 5435 hoge.logger1 - SLF4J_LOGGER1.info() Mar 6 11:30:05 1 2014-03-06T11: 30:05.327+09:00 kyle-wildfly hogeapp 5435 hoge.logger1 - JUL_LOGGER1.info() Mar 6 11:30:05 1 2014-03-06T11: 30:05.327+09:00 kyle-wildfly hogeapp 5435 hoge.logger1 - SLF4J_LOGGER1.info() Mar 6 11:30:05 1 2014-03-06T11: 30:05.765+09:00 kyle-wildfly hogeapp 5435 hoge.logger1 - JUL_LOGGER1.info() Mar 6 11:30:05 1 2014-03-06T11: 30:05.766+09:00 kyle-wildfly hogeapp 5435 hoge.logger1 - SLF4J_LOGGER1.info()
- 出力フォーマットはもう一種類あるみたいなので変えてみる
/subsystem=logging/syslog-handler=SYSLOG1:write-attribute(name="syslog-format", value="RFC3164")
- 出力日時が一個だけになる
Mar 6 11:33:41 kyle-wildfly hogeapp[5435]: JUL_LOGGER1.info() Mar 6 11:33:41 kyle-wildfly hogeapp[5435]: SLF4J_LOGGER1.info()
- 5435って何の数字だろう。WildFlyのPIDかと思ったけど違うし
- シビリティとかロガー名が欠落しているのが残念な気はする
org.jboss.logmanager.handlers.SyslogHandlerを試してみる
- [3]によるとsyslog-handlerよりこっちの方が機能が多いらしい
- そのうちsyslog-handlerにマージされるらしい
- ハンドラを作る。設定はpropertiesに書くんだけど資料っぽいものがないので[7]のソースを見てsetterの名前から類推した
/subsystem=logging/custom-handler=SYSLOG2:add( \
class="org.jboss.logmanager.handlers.SyslogHandler", \
module="org.jboss.logmanager", \
named-formatter=PATTERN, \
level=INFO, \
properties={ \
appName="hogeapp", \
hostname="kyle-wildfly", \
serverHostname="localhost", \
facility="LOCAL_USE_1", \
syslogType="RFC3164" })
- SYSLOG1のアサインを解除してSYSLOG2をアサイン
/subsystem=logging/logger=hoge.logger1:unassign-handler(name=SYSLOG1) /subsystem=logging/logger=hoge.logger1:assign-handler(name=SYSLOG2)
- こんな感じ。ロガー名とシビリティが出た。#012って何だろう
Mar 6 12:15:24 kyle-wildfly hogeapp[5435]: 2014-03-06 12:15:24,646 INFO [hoge.logger1] (default task-11) JUL_LOGGER1.info()#012 Mar 6 12:15:24 kyle-wildfly hogeapp[5435]: 2014-03-06 12:15:24,648 INFO [hoge.logger1] (default task-11) SLF4J_LOGGER1.info()#012 Mar 6 12:15:25 kyle-wildfly hogeapp[5435]: 2014-03-06 12:15:25,144 INFO [hoge.logger1] (default task-12) JUL_LOGGER1.info()#012 Mar 6 12:15:25 kyle-wildfly hogeapp[5435]: 2014-03-06 12:15:25,145 INFO [hoge.logger1] (default task-12) SLF4J_LOGGER1.info()#012
- #012を消すべくフォーマットをいじってみる
- いったんSYSLOG2を消す
/subsystem=logging/logger=hoge.logger1:unassign-handler(name=SYSLOG2) /subsystem=logging/custom-handler=SYSLOG2:remove
- フォーマットいじって作り直し
/subsystem=logging/custom-handler=SYSLOG2:add( \
class="org.jboss.logmanager.handlers.SyslogHandler", \
module="org.jboss.logmanager", \
formatter="%-5p [%c] (%t) %s", \
level=INFO, \
properties={ \
appName="hogeapp", \
hostname="kyle-wildfly", \
serverHostname="localhost", \
facility="LOCAL_USE_1", \
syslogType="RFC3164" })
/subsystem=logging/logger=hoge.logger1:assign-handler(name=SYSLOG2)
- こうなる。シビリティとロガー名も出てるしこれでいいかな。
Mar 6 13:00:20 kyle-wildfly hogeapp[5435]: INFO [hoge.logger1] (default task-10) JUL_LOGGER1.info() Mar 6 13:00:20 kyle-wildfly hogeapp[5435]: INFO [hoge.logger1] (default task-10) SLF4J_LOGGER1.info()
- ちなみにformatterの書き方はlog4jと同じらしい[8]
- 例外とか最大長も考慮するとRFC3164形式ならこんな感じがいいかも
/subsystem=logging/custom-handler=SYSLOG6:add( \
class="org.jboss.logmanager.handlers.SyslogHandler", \
module="org.jboss.logmanager", \
formatter="%-5p [%c] (%t) %s%e", \
level=INFO, \
properties={ \
appName="hogeapp", \
hostname="kyle-wildfly", \
serverHostname="localhost", \
facility="LOCAL_USE_1", \
truncate=false, \
maxLength=1024, \
syslogType="RFC3164" })
/subsystem=logging/logger=hoge.logger1:assign-handler(name=SYSLOG6)
- ログはこんな感じ
Mar 8 10:17:02 kyle-wildfly hogeapp[91739]: INFO [hoge.logger1] (default task-1) 0-1199: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 Mar 8 10:17:02 kyle-wildfly hogeapp[91739]: 89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 Mar 8 10:17:02 kyle-wildfly hogeapp[91739]: INFO [hoge.logger1] (default task-1) exception logging test: java.lang.AssertionError: test#012#011at logger.LogServlet.doGet(LogServlet.java:22)#012#011at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)#012#011at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)#012#011at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)#012#011at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61)#012#011at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)#012#011at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)#012#011at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25)#012#011at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociati Mar 8 10:17:02 kyle-wildfly hogeapp[91739]: onHandler.java:113)#012#011at io.undertow.security.handlers.AuthenticationCallHandler.handleRequest(AuthenticationCallHandler.java:52)#012#011at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45)#012#011at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61)#012#011at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70)#012#011at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)#012#011at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25)#012#011at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)#012#011at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25)#012 Mar 8 10:17:02 kyle-wildfly hogeapp[91739]: #011at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25)#012#011at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240)#012#011at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227)#012#011at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73)#012#011at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146)#012#011at io.undertow.server.Connectors.executeRootHandler(Connectors.java:168)#012#011at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:687)#012#011at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)#012#011at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)#012#011at java.lang.Thread.run(Thread.java:744)#012
- タブや改行がエスケープ(#011と#012)されていたり、長いログが分割されていたりするけどちゃんと抜け漏れなく出てる
- escapeEnabled=“false” にするとエスケープされなくなる
- けどこれやるとUDPでログを送信する場合は、複数行のメッセージが欠ける[10]
- RFC5424形式の方が最大長が長かったりするみたいなので、Linuxとかでまた調べる。ソース見るとSSLやTCPでの送信にも対応しているみたい
- 何故か日本語とかマルチバイト文字が正しく出ない。encoding=“UTF-8” とか入れてみたけど駄目だった。なぜだろう
- 少しソースを追っかけてみると、charをbyte[]に分ける処理とかがあってそのあたりで何かがおかしくなってるようだった。
- 暇があったらプルリクエスト送りたいけど大変そうなのでまたそのうち見てみる
- issueは[11]に上げてプルリクエストも送ってみた
org.apache.log4j.net.SMTPAppenderを使ってみる
ハンドラの設定
- GMail経由でSSLで認証付きで送る方法。詳細な設定は[12][13]あたりを参照
- APサーバに設定したSessionをJNDIで指定できればいいんだけどそういうのはないみたい
/subsystem=logging/custom-handler=LOG4J_SMTP:add( \
class="org.apache.log4j.net.SMTPAppender", \
module="org.apache.log4j", \
formatter="%-5p [%c] (%t) %s%e", \
level=INFO, \
properties={ \
From="jane.doe@gmail.example.com", \
LocationInfo=true, \
SMTPDebug=true, \
SMTPHost="smtp.gmail.com", \
SMTPPort=465, \
SMTPProtocol="smtps", \
SMTPUsername="jane.doe@gmail.example.com", \
SMTPPassword="***", \
Subject="error mail subject", \
To="jane.doe@icloud.example.com", \
BufferSize=256 })
- propertiesにSMTPDebug=trueを追加するとログに通信内容が出るので問題解決にはよいかも
ロガーにハンドラをアサイン
/subsystem=logging/logger=hoge.logger1:assign-handler(name=LOG4J_SMTP)
お試し用サーブレット
- こんな感じでログ出してみる
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
JUL_LOGGER1.info("JUL_LOGGER1.info()");
SLF4J_LOGGER1.error("にほんご えらー");
}
こんなメールがくる

- 日本語出せない問題は少し前に直ったみたい。
本番環境だとどんな感じが良いか
- ファイルハンドラ系で素直に吐き出しておいて、fluentdとかのログ収集の仕組みを別に入れるのが、モダンな感じで良いんじゃなかろうかと思う
- syslog絡めてやるのが良いかなと思うが
- SyslogHandlerで日本語が出せないのがつらい。一応issueは上げておいたけど[11]。
- Log4Jのsyslogappenderは、一部の文言が欠けるのがつらい
- size-rotating-file-handlerとかでローカルに出しつつ(こいつは古いログのパージもやってくれるので)、syslogにも出して、最終的にはどこかのログサーバに集約するとか
org.jboss.logmanager.handlers.SyslogHandlerはExceptionをログに出してくれないようだ。嘘付いてた。formatterに “%e” を設定すると出る。- 実はcustom-loggerではLog4JのAppenderも使えるので、log4jのsyslog用Appenderを使うかと思って試してみたら、確かに例外もログに出るんだけど、何故かスタックトレースやメッセージの一部が欠ける謎の現象が現れるので、あんまり良くない
- あとlog4jのSMTPAppenderのメール通知は状況によっては便利だと思う。WildFlyなら別にjar持ってきたりする必要も無くCLIから設定するだけで使える。
気になる事
- syslogに出すとpidらしきところに5435と表示されるんだが、そんなプロセスは動いてない
kyle-no-MacBook:etc kyle$ ps -Af | grep java | grep 5435 501 54356 42731 0 8:01AM ?? 0:32.26 /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/java -Dprogram.name=JBossTools: WildFly 8.0.0...
- WildFlyは54356なんだけど一番下の桁が欠けてるとかあり得るのだろうか
- 調べたら欠けてた[9]
参考文献
- Logging Configuration - WildFly 8 - Project Documentation Editor
- How To - WildFly 8 - Project Documentation Editor
- Handlers - WildFly 8 - Project Documentation Editor
- 11.5.6. Sample XML Configuration for a Size Log Handler
- Configuring JBoss AS 7.2 to log to syslog - Server Fault
- Logging Configuration - JBoss AS 7.2 - Project Documentation Editor
- GC: SyslogHandler - org.jboss.logmanager.handlers.SyslogHandler (.java) - GrepCode Class Source
- Customizing logging format in Jboss 7 AS | Community
- [LOGMGR-100] SyslogHandler.findPid() omitted the last digit of pid - JBoss Issue Tracker
- [syslog-ng] Extra Lines Truncated
- [LOGMGR-104] SyslogHandler doesn't handle multi-byte characters correctly - JBoss Issue Tracker
- SMTPAppender (Apache Log4j 1.2.17 API)
- Log4J徹底解説~ネットワーク系Appender
Tags: wildfly
WildFly8.0.0CR1でPOSTパラメータの文字化けを回避する
TweetPosted on Thursday Jan 23, 2014 at 04:13PM in Technology
環境
- WildFly8.0.0CR1
- Oracle JRE7u51
設定内容
/WEB-INF/jboss-web.xmlに以下のような内容を書くだけです
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web version="8.0" xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.org/j2ee/schema/jboss-web_8_0.xsd">
<default-encoding>UTF-8</default-encoding>
</jboss-web>
WildFly8は最近HTTPサーバの実装が切り替わったか何かで若干情報が見つかり辛かった。あとアプリ別じゃなくてアプリケーションサーバ全体に同じ設定を適用する手段も参考資料にありました。試してないけど。
あと何故かこの設定を入れなくてもajaxの通信は化けなかった
参考文献
Tags: wildfly
markdown4jで遊ぶ
TweetPosted on Wednesday Jan 22, 2014 at 01:28PM in Technology
環境
- markdown4j 2.2
- WildFly 8.0.0CR1
- Oracle JDK7u51
何をするの?
markdown4jで遊びます。とりあえずサンプルとかありがちなのを動かしてみてどんな感じのhtmlが生成されるか見てみます。
実験用画面も置いておきます
準備
pom.xml
mavenで取ってこれるのでここにあるdependencyを追加します
実験用画面
JSFで画面を作ります
CDI管理Bean
import java.io.IOException;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import org.markdown4j.Markdown4jProcessor;
@Named
@SessionScoped
public class MarkdownBean implements Serializable {
String body;
String md;
public String getMd() {
return md;
}
public void setMd(String md) {
this.md = md;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public void process() throws IOException {
md = new Markdown4jProcessor().process(body);
}
}
Faceletsページ
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head></h:head>
<body>
<h:form>
<h:inputTextarea value="#{markdownBean.body}" cols="80" rows="5"
id="input" />
<br />
<h:commandButton action="#{markdownBean.process()}" value="process">
<f:ajax execute="input" render="md md2" />
</h:commandButton>
<div>
<h:outputText value="#{markdownBean.md}" id="md" />
</div>
<hr />
<div>
<h:outputText value="#{markdownBean.md}" id="md2" escape="false" />
</div>
</h:form>
</body>
</html>
動かしてみる
遊ぶ
markdown4jのページにあるサンプル
最後の方は外部サービス連携みたいですが便利ですね
さらに遊ぶ
# 見出し1
## 見出し2
段落1ああああああああああああああああああああああああああああああああああああああああああああああああああ
段落2
[リンク](http://www.google.com/)

``` java
class hoge{
private int hoge;
private int hoge2;
}
```
参考文献
Tags: markdown
