JBoss AS7でSAStrutsを動くようにしてみた

前回の続き。

Seasar2のソースを見てみたら、JBoss AS7のVFS API依存になってしまうが対応できそうなので、JBoss AS7向けの拡張モジュール(s2-jbossas7)を作ってみた。SAStruts+S2JDBC程度の簡単なサンプルでしか動作確認していませんが、公開しておきます。WARファイル形式、展開WAR形式の両方で確認しています。なお、Seasar2のJARは/WEB-INF/lib以下にあることが前提です。$JBOSS_HOME/modules以下に置いた場合は試していないです。

ついでにJBoss AS7はServlet 3.0対応しているので、@WebServletを使って設定も少し減らしてみた(他の設定があるのでほとんど無意味だけどね)。

ソースはGitHubにあります。また、バイナリファイルもGitHub上のMavenリポジトリに置いておいたので、Mavenから簡単に使えます。JARだけ欲しい場合はこちら

確認した環境

JDK 1.7.0_05-b05
JBoss AS 7.1.1.Final
SAStruts 1.0.4-sp9

使い方

pom.xmlの変更
...
  <repositories>
    <repository>
      <id>maven.seasar.org</id>
      <name>The Seasar Foundation Maven2 Repository</name>
      <url>http://maven.seasar.org/maven2</url>
    </repository>
    <!-- 以下を追加 -->
    <repository>
      <id>maven.wadahiro.github.com</id>
      <name>The wadahiro's Maven2 Repository</name>
      <url>http://wadahiro.github.com/maven/release</url>
    </repository>
  </repositories>
...
  • s2-jbossas7への依存関係を追加する。
...
    <!-- SAStruts -->
    <dependency>
      <groupId>org.seasar.sastruts</groupId>
      <artifactId>sa-struts</artifactId>
      <version>1.0.4-sp9</version>
    </dependency>
    <!-- 以下を追加 -->
    <dependency>
      <groupId>org.seasar.jboss</groupId>
      <artifactId>s2-jbossas7</artifactId>
      <version>0.1</version>
    </dependency>
...
web.xmlの変更
  • web-appタグをServlet 3.0の物に変更する。
<web-app 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_3_0.xsd"
      version="3.0"> 
  • S2ContainerServletの定義を削除(またはコメントアウト)する。
...
  <!-- 
  <servlet>
    <servlet-name>s2container</servlet-name>
    <servlet-class>org.seasar.framework.container.servlet.S2ContainerServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
  </servlet>
  -->
...
  <!--
  <servlet-mapping>
    <servlet-name>s2container</servlet-name>
    <url-pattern>/s2container</url-pattern>
  </servlet-mapping>
  -->
...

もし、web.xmlに明示的に書くのであれば、S2ContainerServletの代わりにorg.seasar.framework.container.servlet.S2ContainerServletOnJBossAS7を定義してください。その場合は、web-appタグは旧来の物でも構いません。

動かしてみる

前回と違ってデプロイ成功。サンプルアプリも動作しています。

10:28:25,839 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015876: Starting deployment of "sastruts-sample.war"
10:28:26,859 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-6) Class Path entry commons-beanutils.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
10:28:26,861 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-6) Class Path entry commons-digester.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
10:28:26,862 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-6) Class Path entry commons-fileupload.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
10:28:26,863 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-6) Class Path entry commons-logging.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
10:28:26,864 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-6) Class Path entry commons-validator.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
10:28:26,865 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-6) Class Path entry jakarta-oro.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
10:28:27,325 INFO  [org.seasar.struts.validator.S2ValidatorPlugIn] (MSC service thread 1-2) Loading validation rules file from '/WEB-INF/validator-rules.xml'
10:28:27,374 INFO  [org.seasar.framework.container.factory.SingletonS2ContainerFactory] (MSC service thread 1-2) s2-frameworkのバージョンは2.4.44です。
10:28:27,376 INFO  [org.seasar.framework.container.factory.SingletonS2ContainerFactory] (MSC service thread 1-2) s2-extensionのバージョンは2.4.44です。
10:28:27,381 INFO  [org.seasar.framework.container.factory.SingletonS2ContainerFactory] (MSC service thread 1-2) s2-tigerのバージョンは2.4.44です。
10:28:27,688 INFO  [org.seasar.framework.container.factory.SingletonS2ContainerFactory] (MSC service thread 1-2) Running on [ENV]ct, [DEPLOY MODE]Hot Deploy
10:28:27,690 INFO  [org.jboss.web] (MSC service thread 1-2) JBAS018210: Registering web context: /sastruts-sample
10:28:27,728 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018565: Replaced deployment "sastruts-sample.war" with deployment "sastruts-sample.war"

JBoss AS7でSAStrutsが動かず

JBoss AS4系で動かしていたSeasarベースのアプリをそろそろJBoss AS7に移行するかもしれないなんて話が出てきたので、そもそも動くのかどうか単純なSAStrutsのサンプルで検証してみた。結果、JBoss AS5の頃にVFS対応されていましたが、7では見事に動かず。。。

環境

  • JDK 1.7.0_05-b05
  • JBoss AS 7.1.1.Final
  • SAStruts 1.0.4-sp9

試した手順

MavenSAStrutsのサンプルアプリを生成

mvn archetype:generate -DarchetypeRepository=https://www.seasar.org/maven/maven2/ \
    -DarchetypeGroupId=org.seasar.sastruts \
    -DarchetypeArtifactId=sa-struts-archetype -DarchetypeVersion=1.0.4-sp9 \
    -DgroupId=org.example.sastuts -DartifactId=sastruts-sample -Dversion=1.0

ビルド

mvn package

でtarget/sastruts-sample.warができる。

デプロイ!

できたWARファイルを$JBOSS_HOME/standalone/deploymentsにコピーしてデプロイする。

結果、以下のようにvfs:・・・というプロトコルが解釈できずにエラーになる。

18:42:38,332 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-2) JBAS015876: Starting deployment of "sastruts-sample.war"
42.351: [GC 42.351: [ParNew: 117354K->13056K(118016K), 0.0836350 secs] 117354K->31464K(511232K), 0.0836940 secs] [Times: user=0.20 sys=0.03, real=0.08 secs] 
18:42:39,151 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry commons-beanutils.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
18:42:39,152 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry commons-digester.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
18:42:39,152 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry commons-fileupload.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
18:42:39,153 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry commons-logging.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
18:42:39,154 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry commons-validator.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
18:42:39,155 WARN  [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry jakarta-oro.jar in "/content/sastruts-sample.war/WEB-INF/lib/struts-1.2.9.jar"  does not point to a valid jar for a Class-Path reference.
43.114: [GC 43.114: [ParNew: 118016K->13056K(118016K), 0.0759070 secs] 136424K->56906K(511232K), 0.0759690 secs] [Times: user=0.19 sys=0.01, real=0.08 secs] 
18:42:40,014 INFO  [org.seasar.struts.validator.S2ValidatorPlugIn] (MSC service thread 1-5) Loading validation rules file from '/WEB-INF/validator-rules.xml'
18:42:40,082 INFO  [org.seasar.framework.container.factory.SingletonS2ContainerFactory] (MSC service thread 1-5) s2-frameworkのバージョンは2.4.44です。
18:42:40,084 INFO  [org.seasar.framework.container.factory.SingletonS2ContainerFactory] (MSC service thread 1-5) s2-extensionのバージョンは2.4.44です。
18:42:40,085 INFO  [org.seasar.framework.container.factory.SingletonS2ContainerFactory] (MSC service thread 1-5) s2-tigerのバージョンは2.4.44です。
18:42:40,270 WARN  [org.seasar.framework.util.ResourcesUtil] (MSC service thread 1-5) ルートパッケージ(org.example.sastruts)に対応するURL(vfs:/content/sastruts-sample.war/WEB-INF/classes/org/example/sastruts/)のプロトコルが不明です。
18:42:40,272 WARN  [org.seasar.framework.util.ResourcesUtil] (MSC service thread 1-5) ルートパッケージ(org.example.sastruts)に対応するリソースがクラスパスから見つかりませんでした。
18:42:40,392 WARN  [org.seasar.framework.util.ResourcesUtil] (MSC service thread 1-5) ルートパッケージ(org.example.sastruts)に対応するURL(vfs:/content/sastruts-sample.war/WEB-INF/classes/org/example/sastruts/)のプロトコルが不明です。
18:42:40,393 WARN  [org.seasar.framework.util.ResourcesUtil] (MSC service thread 1-5) ルートパッケージ(org.example.sastruts)に対応するリソースがクラスパスから見つかりませんでした。
18:42:40,398 WARN  [org.seasar.framework.container.assembler.BindingTypeShouldDef] (MSC service thread 1-5) org.seasar.extension.dbcp.impl.ConnectionPoolImplのプロパティ(XADataSource)が見つからないので設定をスキップします
18:42:40,402 WARN  [org.seasar.framework.util.ResourcesUtil] (MSC service thread 1-5) ルートパッケージ(null)に対応するURL(vfs:/content/sastruts-sample.war/WEB-INF/lib/s2-tiger-2.4.44.jar/)のプロトコルが不明です。
18:42:40,404 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/sastruts-sample]] (MSC service thread 1-5) StandardWrapper.Throwable: java.lang.NullPointerException
	at org.seasar.framework.container.autoregister.ComponentAutoRegister.registerAll(ComponentAutoRegister.java:62) [s2-framework-2.4.44.jar:]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_05]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_05]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_05]
	at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_05]
	at org.seasar.framework.util.MethodUtil.invoke(MethodUtil.java:96) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.assembler.AbstractMethodAssembler.invoke(AbstractMethodAssembler.java:94) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.assembler.DefaultInitMethodAssembler.assemble(DefaultInitMethodAssembler.java:49) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.deployer.SingletonComponentDeployer.assemble(SingletonComponentDeployer.java:69) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.deployer.SingletonComponentDeployer.deploy(SingletonComponentDeployer.java:48) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.deployer.SingletonComponentDeployer.init(SingletonComponentDeployer.java:76) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.impl.ComponentDefImpl.init(ComponentDefImpl.java:236) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:563) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:560) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:560) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.factory.SingletonS2ContainerFactory.init(SingletonS2ContainerFactory.java:167) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.servlet.SingletonS2ContainerInitializer.initialize(SingletonS2ContainerInitializer.java:55) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.servlet.S2ContainerServlet.initializeContainer(S2ContainerServlet.java:139) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.servlet.S2ContainerServlet.init(S2ContainerServlet.java:127) [s2-framework-2.4.44.jar:]
	at javax.servlet.GenericServlet.init(GenericServlet.java:242) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1202) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1102) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3655) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:3873) [jbossweb-7.0.13.Final.jar:]
	at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:90) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [rt.jar:1.7.0_05]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [rt.jar:1.7.0_05]
	at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_05]

18:42:40,415 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/sastruts-sample]] (MSC service thread 1-5) サーブレット /sastruts-sample がload()例外を投げました: java.lang.NullPointerException
	at org.seasar.framework.container.autoregister.ComponentAutoRegister.registerAll(ComponentAutoRegister.java:62) [s2-framework-2.4.44.jar:]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_05]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_05]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_05]
	at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_05]
	at org.seasar.framework.util.MethodUtil.invoke(MethodUtil.java:96) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.assembler.AbstractMethodAssembler.invoke(AbstractMethodAssembler.java:94) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.assembler.DefaultInitMethodAssembler.assemble(DefaultInitMethodAssembler.java:49) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.deployer.SingletonComponentDeployer.assemble(SingletonComponentDeployer.java:69) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.deployer.SingletonComponentDeployer.deploy(SingletonComponentDeployer.java:48) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.deployer.SingletonComponentDeployer.init(SingletonComponentDeployer.java:76) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.impl.ComponentDefImpl.init(ComponentDefImpl.java:236) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:563) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:560) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:560) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.factory.SingletonS2ContainerFactory.init(SingletonS2ContainerFactory.java:167) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.servlet.SingletonS2ContainerInitializer.initialize(SingletonS2ContainerInitializer.java:55) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.servlet.S2ContainerServlet.initializeContainer(S2ContainerServlet.java:139) [s2-framework-2.4.44.jar:]
	at org.seasar.framework.container.servlet.S2ContainerServlet.init(S2ContainerServlet.java:127) [s2-framework-2.4.44.jar:]
	at javax.servlet.GenericServlet.init(GenericServlet.java:242) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1202) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1102) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3655) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:3873) [jbossweb-7.0.13.Final.jar:]
	at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:90) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [rt.jar:1.7.0_05]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [rt.jar:1.7.0_05]
	at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_05]

18:42:40,428 INFO  [org.jboss.web] (MSC service thread 1-5) JBAS018210: Registering web context: /sastruts-sample
18:42:40,472 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "sastruts-sample.war

My IMAPサーバを再構築 (Fetchmail+Dovecot+Pigeonhole(Sieve))

2008年頃に構築したMy IMAPサーバ(以下の記事で書いていました)を再構築したのでメモ。

この時はcoLinuxを使ってWindows上でLinuxを走らせ、DovecotIMAPサーバを構築した。今回、使用していたWindowsPCをESXiサーバに入れ替えてしまったため、ESXi上に再構築することにした。

今回の移行方針

OS

以前はFedoraを何となく入れていたが、普段からなれているCentOS 6.2に変更。ディスク容量&メモリ使用量節約のため不要なソフトウェアは極力入れず、サービスも最低限起動することを基本方針とする。

IMAPサーバ

今までと同じでDovecotを使用する。ただし、メール振り分けはProcmailを使わず、Sieveを使うことにした。Seiveとは、電子メールフィルタリングのためのプログラミング言語で、Dovecotもサポートしている。

例えば、Sieveでは振り分けルールを以下のように書くことができる。非常にシンプルなので*1Procmailのレシピより読み易い。

if address :contains ["From", "To"] "@sourceforge.net" {
   fileinto "ML;
}

今回Sieveにした理由は以下の2点。

なお、Dovecot2系からはSieveはPigeonholeでサポートされているので、これを使う。

メールの取得〜Mailderへの格納

今までと同じでFetchmailを使用する。以前はFetchmailでメールサーバから取得したメールをProcmailに渡してMailDirに格納していたが、振り分けには前述の通りSieveを利用するので、直接Dovecotに渡すこととする。

構築手順

OSインストール

CentOSCentOS-6.2-x86_64-minimal.isoを使って、最小構成でインストールする。
なお、VMのメモリは512MBに設定。これは設定完了後に下げます*2

不要なサービスの停止

私の環境では以下のサービスを停止にした。今のところ問題は起きていないけど自己責任で。

  • auditd
  • ip6tables
  • iptables
  • netfs
  • nfslock
  • rpcbind
  • rpcgssd
  • rpcidmapd
  • iscsi
  • iscsid
  • lvm2-monitor
  • fcoe
  • lldpad

必要なソフトウェアのインストール

yumでさくっとインストール完了。

yum install fetchmail dovecot dovecot-pigeonhole

Fetchmailの設定

  • $HOME/.fetchmailrcの作成

以前作成したのとほぼ同じ。変わったのは、Procmailに渡していたところ。ここを、Dovecotに渡すようにする。"/usr/libexec/dovecot/deliver"とする。
また、設定に失敗してメールが消えないように、とりあえず"keep"を設定しておこう。

# directory for log
#set logfile "/home/hogehoge/fetchmail.log"

# destination for fetchmail error
set postmaster root
set no bouncemail

defaults
        protocol pop3
        keep
        no mimedecode

poll pop3.example.org
        protocol pop3
        user foo
        password bar
        mda "/usr/libexec/dovecot/deliver"

以前作成したのと全く同じ。サービス化しちゃってますが、別にcronで動作させてもOK。

#!/bin/sh
#
# chkconfig: 345 99 20
#
# description: Fetchmail auto start script

# Source function library.
. /etc/rc.d/init.d/functions

# See how we were called.
case "$1" in
  start)
        for user in `ls /home/`
        do
                if [ -f /home/$user/.fetchmailrc ]; then
                        echo "fetchmail for $user starting..."
                        su $user -c "/usr/bin/fetchmail --daemon 60"
                fi
        done
        ;;
  stop)
        # Stop daemons.
        for user in `ls /home/`
        do
                if [ -f /home/$user/.fetchmailrc ]; then
                        echo "fetchmail for $user stoping..."
                        su $user -c "/usr/bin/fetchmail --quit"
                fi
        done
        ;;
  *)
        echo "Usage: $0 {start|stop}"
        exit 1
esac

exit 0

Dovecotの設定

  • MailDirの設定を行う。
mail_location = maildir:~/Maildir
  • IMAPサーバの設定を行う。
protocols = imap
    • /etc/dovecot/conf.d/10-master.conf
service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
  • Sieveを有効にする。
    • /etc/dovecot/conf.d/15-lda.conf
protocol lda {
  # Space separated list of plugins to load (default is global mail_plugins).
  mail_plugins = $mail_plugins sieve
}
    • /etc/dovecot/conf.d/20-managesieve.conf
protocols = $protocols sieve
    • /etc/dovecot/conf.d/90-sieve.conf
plugin {
  sieve = ~/.dovecot.sieve
  sieve_global_path = /var/lib/dovecot/sieve/default.sieve
  sieve_dir = ~/sieve
  sieve_global_dir = /var/lib/dovecot/sieve/

Thunderbirdから接続してみる。

IMAPで繋がることを確認。

SieveのAdd-Onをインストール

ThunderbirdのAdd-OnThunderbirdにインストールする。

Sieveによる振り分け設定

インストールするとThunderbirdのアカウント設定に「Sieve Settings」が登場する。そこから、「Yes, manage Sieve scripts for this account」を選択して保存する。
f:id:Hirohiro:20120707192240p:plain

有効にしたら、ツール>Sieve Filter Settingからフィルタの設定を開く。フィルタは複数作成できるが、有効にできるのは1つだけなので注意。画面右の「Edit」をクリックしてフィルタの編集画面を開く。
f:id:Hirohiro:20120707192227p:plain

Seieveのソース編集画面が開く。ここで振り分けルールを直接記述しても良いが、「Source」をクリックするとGUIでの設定に切り替わる。
f:id:Hirohiro:20120707192245p:plain

画面右の「Action」「Tests」「Operators」からドラッグ&ドロップで各コマンドを配置し、詳細設定を行うことができる。
f:id:Hirohiro:20120707192251p:plain

*1:その分言語としては制限が多い

*2:ある程度メモリを割り当てないとインストールできないようです

Struts 1.3 + Spring 2.5のサンプルアプリ(ついでにGradle化)

古いけど動いているシステムではよく使われていそうなStruts 1.3 + Spring 2.5の組み合わせのシンプルなサンプルアプリが急遽必要になったので、探してみると意外とちょうど良いのが見つからない。
Struts + Spring + Hibernate integration example
からダウンロードできるものがHibernateを使っているけど、シンプルで良さそう。

というわけでこれをちょっと修正して用意してみた。ついでにGradle化なんてしてみたり(オリジナルはMavenです)。

修正版はGitHubにあげておきました。
https://github.com/wadahiro/struts-spring-example

以下、修正内容と使い方について説明しておきます。

修正内容

データベースをMySQLからH2Databaseに変更

オリジナルはMySQLが必要。サンプルなのでさくっと動かしたいので組み込みDBのH2Databaseに変更。テーブルの初期化も自動実行されるようにH2Databaseを設定。

HibernateからSpring JDBC Templateに変更

オリジナルはDAOはHibernateを使っているけど、今回Hibernateは不要なのでSpring JDBC Templateに変更。不要なHibernateの設定ファイルを削除し、DAOクラスの実装を修正しました。

ビルドツールをMavenからGradleに変更

pom.xml -> build.gradleにすると132行から32行に減った。やっぱXMLは冗長だなぁと思う。
ついでにJetty Pluginも使えるようにして(といっても1行追記しただけど)、簡単にサーバ上で動かせるようにした。

Springのコンフィグファイルをクラスパス経由で読むように変更

GradleのJetty Pluginで最初動かそうとすると、Springのコンフィグファイルをファイルパスから読んでいて動かず。クラスパス経由で読むように微修正。

マルチバイト対応

Jettyだと問題ないけど、ビルドしたWARをTomcatやJBossにデプロイすると見事に文字化けする。対策として、SetCharacterEncodingFilter クラスを追加しweb.xmlでフィルターとして組み込みつつ、各JSPエンコード設定を追加。

使い方

GitHubからcloneし、Eclipseで色々いじりたい人は以下のコマンドプロジェクト直下で実行し、インポートしてください。Struts、Springなどの必要なJARもこの時に自動取得するので、インターネット接続は必須です。

gradlew eclipse

アプリケーションを動かしたい場合は、以下のコマンドをプロジェクト直下で実行する。
なお、環境変数JAVA_HOMEを設定していないと動かないので注意。

gradlew jettyRun

以下のようにコンパイル後、Jettyが起動します。Running at ... で停止するので、その状態になったら表示されているURLにアクセスすればサンプルを動かせます。止めたい場合は、Ctrl+c でOK。

C:\Users\wadahiro\git\struts-spring-example>gradlew jettyRun
:compileJava
注意:C:\Users\wadahiro\git\struts-spring-example\src\main\java\com\mkyong\custom
er\dao\impl\CustomerDaoImpl.javaの操作は、未チェックまたは安全ではありません。
注意:詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください。
警告1:processResources UP-TO-DATE
:classes
> Building > :jettyRun > Running at http://localhost:8080/struts-spring-example

なお、Jetty上のサンプルアプリをデバッグしたい場合は、Eclipseなどからリモートデバッグを行えばOK。Jettyはgradle経由で起動させているので、実行前にデバッグモードのオプションを環境変数に設定しておけば良い。
Windowなら、

set GRADLE_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n 

MacやLinuxなら、

export GRADLE_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"

と設定してからGradleを実行すれば良い。なお、Gradleの実行時に--daemonは付けないように注意。--daemonで起動すると別のプロセスで動いてしまうので。

TomcatやJBossにデプロイしたい場合は、以下のコマンドをプロジェクト直下で実行する。build/libs以下にWARファイルが生成されるのでそれをデプロイすればOK。

gradlew war

はてなブログで記事の先頭にはてなスターとはてブボタンを表示させてみた

はてなブログだとダイアリーと異なり、記事の先頭にスターが表示されないんですね... ちょっと違和感があるので、JavaScriptで先頭にも表示するようにしてみた。

あと、ついでにはてなブックマークのボタンも先頭に表示してみた。各記事内だけでなくブログのトップページにも表示し、そこからブログ記事ごとにブックマーク可能なようにしています。

使いたい方は複製改変ご自由にどうそ。

使い方

  • サイドバーにHTMLのモジュールを追加し、以下のコードを貼付けます。
  • はてブのURLはご自身のブログURLに変更してください(http://wadahiro.hatenablog.comの箇所)。
<script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button_wo_al.js" charset="utf-8" async="async"></script>
<script type="text/javascript">
$(document).ready(function() {
    var footers = $("p.entry-footer-section");
    var headers = $(".entry-header");

    headers.each(function(index, header) {
        var footer = $(footers[index]);

        $(header).append("<br>");
        $(header).append($(footer));

        // Hatena Bookmark
        var titleLink = $(header).find(".entry-title a");
        var url = titleLink.attr("href");
        var title = titleLink.text();

        $(header).append('<a href="http://b.hatena.ne.jp/entry/http://wadahiro.hatenablog.com' + url + '" class="hatena-bookmark-button" data-hatena-bookmark-title="' + title + '" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;" /></a>');
    });

});
</script>

はてなブログに移行しました

本日、はてなブログに、はてなダイアリーからのインポート機能を追加しました。3ステップのかんたん操作で、はてなダイアリーの記事・コメントと、記事に付けられたはてなスターはてなブックマークをすべてはてなブログに移行できます。

http://staff.hatenablog.com/entry/2012/05/31/152104

というわけで、インポート機能を使ってダイアリーから移行してみました!

ちゃんと移行できてるようです。昔の記事内にある自分の記事へのリンクをクリックしても、移行後の記事にリダイレクトもされておりリンク切れもなさそう。

ついでにタイトルも変更。wadahiro.hatenablog.comが取れたので、Hirohiroの日記からwadahiroの日記に変えました。IDも変更したいけどできないようなのでそこは今まで通りid:Hirohiroです:-(。

JVM(Jython)上でSphinxを動かしてみた

使い道がないかもしれないが... 以下を参照すると、Jython上でPygmentsは動かないがいけるっぽい。

ただし、autodocは動かないという情報も。やはり完全互換は難しいか。拡張機能を使うと他にも動かない部分があるかも。

試しに作ったものをDropBoxにおいておきました。

ソースはこちら。

使い方

zipを解凍すると、binディレクトリ以下にsphinx4jコマンドがあるのでこれを実行する。使用コマンドは以下の通り。

Usage: sphinx4j commands
Commands:
    install            -- install sphinx into your home directory
    sphinx-quickstart  -- run sphinx-quickstart
    sphinx-build       -- run sphinx-build
sphinx4j sphinx-build -b html source build

2012/05/05追記

  • sphinx-buildのコマンド例が間違っていたので修正。