Seasar DI Container with AOP

セットアップ

Seasar2と同様にJDK1.4以上が必要です。

S2Mai本体

ダウンロードしたs2mai-x.x.x.zipを解凍すると、s2maiディレクトリが出来ます。そのなかのlibディレクトリにある「s2mai-x.x.x.jar」をクラスパスに含めて下さい。

他、必要となるjarファイルもlibディレクトリ内にありますが、その内、S2Mai本体が必要とするものは以下になります。

  • mail-x.x.jar
  • activation-x.x.x.jar
  • ozacc-mail-x.x.x.jar
  • s2-framework-2.4.x.jar
  • s2-exteinsion-2.4.x.jar

テンプレートエンジンとして、FreeMarkerとVelocityに対応しています。ご利用になるテンプレートエンジンによって以下のいずれかをクラスパスに含めて下さい。

FreeMarkerの場合
  • freemarker-x.x.x.jar
Velocityの場合
  • velocity-x.x.jar
  • velocity-tools-generic-x.x.jar
  • commons-collections-x.x.jar
  • commons-lang-x.x.jar

後述しますが、添付ファイルをListで持つ場合にジェネリクスを使いたい場合は、下記のjarが必要となります。こちらは配布ファイルには含まれていませんので別途入手して下さい。

  • s2-tiger-2.4.x.jar
  • geronimo-ejb_2.1_spec-1.0.jar

geronimo-ejb_2.1_spec-1.0.jarは、動作環境がJavaEEにフルに対応している場合は不要となります。詳しくはこちらをご参照下さい。

注意!!

geronimo-j2ee_1.4_spec-1.0.jar がクラスパスにある場合、こちらにもJavaMailが部分的に実装されており、参照順序によってこちらが優先されると不具合が発生する事が確認されています。出来る限りSUNのJavaMail実装(ここではmail.jar)を使うようにして下さい。

S2Mai-Tiger

S2Maiでは定数アノテーションを用いて各種プロパティを設定する事が出来ます。これを定数ではなく、Javaのアノテーションを使って設定する事が出来ます。その際には、s2mai-tiger-x.x.x.zipをダウンロードした後、解凍し、それに含まれる「s2mai-tiger-x.x.x.jar」をクラスパスに含めて下さい。

Maven2からのご利用

S2MaiはMaven2からもご利用いただけます。まず、SeasarのMaven2リポジトリのrepository要素を追加します。

  <repositories>
    <repository>
      <id>maven.seasar.org</id>
      <name>The Seasar Foundation Maven2 Repository</name>
      <url>http://maven.seasar.org/maven2</url>
    </repository>
  </repositories>

そして、S2MaiもしくはS2Mai-Tigerをdependencies要素の中に追加して下さい。S2Mai-Tigerをご利用の場合は、S2Maiへの依存はMaven2が解決しますので、要素を追加する必要はありません。

<dependency>
    <groupId>org.seasar.mai</groupId>
    <artifactId>s2mai</artifactId>
    <version>0.9.4</version>
</dependency>
<dependency>
    <groupId>org.seasar.mai</groupId>
    <artifactId>s2mai-tiger</artifactId>
    <version>0.9.4</version>
</dependency>

versionは適宜指定して下さい。

まずは使ってみる

全体の設定

SMTPサーバの設定やエンコーディングなど、全体の設定は「mailProperties.dicon」というファイルに記述します。このファイルはjarに含まれているので、下記のデフォルト値で問題がなければ作成する必要はありません。設定の変更をしたい場合にはファイルを作成し、設定を記述してルートパッケージに置きます。

デフォルトの内容は以下になります。

mailProperties.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.3//EN"
    "http://www.seasar.org/dtd/components23.dtd">
<components namespace="mailProperties">
    <component name="host">
        "localhost"
    </component>
    <component name="port">
        25
    </component>
    <component name="username">
        null
    </component>
    <component name="password">
        null
    </component>
    <component name="from">
        null
    </component>
    <component name="replyTo">
        null
    </component>
    <component name="returnPath">
        null
    </component>
    <component name="messageId">
        null
    </component>
    <component name="templateEncoding">
        "UTF-8"
    </component>
    <component name="connectionTimeout">
        10000
    </component>
    <component name="readTimeout">
        10000
    </component>
    <component name="mailCharset">
        "ISO-2022-JP"
    </component>
</components>
各設定項目の内容は以下です。
host
SMTPサーバ名もしくはIP
port
SMTPのポート番号
username
SMTPにログインする必要がある場合、そのユーザー名
password
同じく、そのパスワード
templateEncoding
テンプレートのエンコーディング
connectionTimeout
SMTPサーバとの接続タイムアウト
readTimeout
SMTPサーバへの送受信時のタイムアウト
mailCharset
メールのエンコードに使用する文字コード
他の項目は現在未対応です。

基本的な使い方

まず、メールの内容を保持するクラスを作ります。ここでは、nameというプロパティを持った「TestDto」というクラスを「s2mai.test.dto」というパッケージに作る事にします。

s2mai.test.dto.TestDto
package s2mai.test.dto;

public class TestDto{
    private String name;
    
    public void setName(String name_){
      this.name = name_;
    }
    
    public String getName(){
      return name;
    }
}

次に、メール送信をするMaiインタフェースを作ります。ここでは「TestMai」というインタフェースを「s2mai.test.mai」というパッケージに作る事にします。「TestMai」は、「TestDto」を引数にとってその内容を反映したメールを送信する「sendMail」というメソッドを持つ事にします。

s2mai.test.mai.TestMai
package s2mai.test.mai;

public interface TestMai {
    void sendMail(TestDto dto);
}

このインタフェースの名前はなんでも構いませんが、後々のメンテナンスやSMART deployを用いた開発に対応するために、「〜Mai」という命名規則に則る事を推奨します。また、メール送信用メソッドの名前には特に制約はありません。用途別に複数のメソッドを一つのMaiインタフェースに定義する事も出来ます。

次に、任意のdiconファイルにMaiをコンポーネントとして登録します。ここでは、「maitest.dicon」というファイルをルートパッケージに作り、そこで定義する事にします。

maitest.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.3//EN"
    "http://www.seasar.org/dtd/components23.dtd">
<components>

    <include path="s2mai.dicon"/>
    
    <component class="s2mai.test.mai.TestMai">
        <aspect>s2MaiInterceptor</aspect>
    </component>
    
</components>

s2mai.diconをincludeし、<aspect>タグで、s2MaiInterceptorを適用します。s2mai.diconはjarの中にありますのでカスタマイズしない限りは何もしなくて構いません。

次に、fromやtoといったメールの設定を保持するdiconファイルを、Maiインタフェースと同じパッケージに作ります。ここでは「s2mai.test.mai」に作る事になります。diconファイルのファイル名は下記の二通りが使用できます。

  • Maiインタフェース名.dicon
  • Maiインタフェース名_メソッド名.dicon

Maiインタフェース名のみのファイル名の場合、Maiインタフェースに複数のメソッドがある場合、それら全てに適用されます。あるメソッドだけに適用したい場合は、Maiインタフェース名_メソッド名の形式にします。

ここでは、メソッドを指定する形にしてみます。

TestMai_sendMail.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.3//EN"
    "http://www.seasar.org/dtd/components23.dtd">
<components>

    <component class="com.ozacc.mail.Mail">
        <initMethod name="addTo"><arg>"rokugen@example.com"</arg></initMethod>
    </component>

</components>

上記は、Toに「rokugen@example.com」を追加しています。ozaccさんの作られたozacc-mail-libraryのMailクラスに直接設定してますので、他のプロパティなど詳しい情報はhttp://spring-ext.sourceforge.jp/oml/apidocs/com/ozacc/mail/Mail.htmlを参照して下さい。

次に、送信メールの内容のテンプレートを作ります。デフォルトではテンプレートエンジンとしてFreeMarkerが使われます。ファイル名は、「Maiインタフェース名_メソッド名.ftl」として下さい。ftlはFreeMarkerのテンプレートの拡張子となります。これを、Maiインタフェースと同じパッケージに置きます。

TestMai_sendMail.ftl
Subject: テストメールです。

${data.name}さんこんにちは。

テンプレートの一番上の行に、「Subject: (最後に半角スペース一個)」と書くと、それ以降を件名としてセットします。例えば件名に「第X回」や「vol.1」など動的な項目があってデータを埋め込みたい時などに便利です。

「Subject:〜」を書いた場合、本文との間に空行を1行入れて下さい。「Subject:〜」を書かない場合は1行目から本文とみなしますので空行は要りません。

mailProperties.diconのtemplateEncodingでUTF-8を指定してますので、UTF-8で保存します。メールの内容を保持するクラス(ここではTestDtoクラス)のプロパティを埋め込む場合には、「${data.property名}」と書きます。テンプレート内でTestDtoを表す要素名は「data」固定です。

では、実行してみましょう。

S2Container container = S2ContainerFactory.create("maitest.dicon");
TestMai mai = (TestMai) container.getComponent(TestMai.class);
TestDto dto = new TestDto();
dto.setName("六");
mai.sendMail(dto);
すると、下記の内容でメールが送信されます。
From:null
To:rokugen@example.com
(他省略)
Subject:テストメールです。

六さんこんにちは。

これが基本的なS2Maiの使い方です。

アノテーションを使った設定

基本的な使い方ですと、送信先などメールの設定をdiconファイルに書く際に、ozacc-mail-libraryのAPIを踏まえていないといけません。S2Maiは、Maiインタフェースに対してアノテーションを追加する事により、FromやToなどを設定する事が出来ますので、アノテーション機能を用いる事により、diconでの設定を回避する事が出来ます。

ここでは、先のサンプルで用いた「TestMai」にアノテーションを追加してみます。アノテーションにはJavaのアノテーションと定数アノテーションの二通りが指定出来ますが、まずは定数アノテーションを使ってみましょう。

s2mai.test.mai.TestMai
public interface TestMai {
    static final String FROM = "hoge@foo.com";
    static final String TO = "rokugen@example.com";
    
    void sendMail(TestDto data);
}

これで、先ほど作った「TestMai_sendMail.dicon」は不要となります。また、先程のサンプルではnullとなっていたFromを「hoge@foo.com」として追加してみました。

このアノテーションの指定方法の場合、一つのMaiに複数のメソッドがある場合でも各メソッドに共通に適用されます。メソッド単位で指定する場合は、「メソッド名_設定項目名」という定数名にします。

s2mai.test.mai.TestMai
public interface TestMai {
    static final String FROM = "hoge@foo.com";
    static final String TO = "rokugen@example.com";
    static final String sendMail2_TO = "kei@example.com";
    
    void sendMail(TestDto data);
    void sendMail2(TestDto2 data);
    void sendMail3(TestDto3 data);
}

この場合、sendMailとsendMail3の実行時にToには「rokugen@example.com」が設定されて、sendMail2の実行時には「kei@example.com」が反映されます。ToやCcやBccなど、複数指定するものには、配列での指定も出来ます。

また、メールアドレスには、「六<rokugen@example.com>」といったように、アドレス本体と合わせて名称を設定したい事があります。S2Maiでは、メールアドレスと名称を保持する、「org.seasar.mai.mail.MailAddress」というクラスを提供しています。

配列での複数指定とMailAddressクラスの使用例を合わせて見てみましょう。

static final MailAddress FROM = new MailAddress("hoge@foo.com","送信元名");
static final MailAddress[] TO = 
    new MailAddress[]{new MailAddress("rokugen@example.com","六"), new MailAddress("mai@example.com","まい")};

MailAddressのコンストラクタの引数は、第一がメールアドレス、第二が名前になります。第二は省略可能です。MailAddress自体では、メールアドレスのフォーマットなど、規定に外れていても特にエラーは起きませんが、最終的にJavaMailのInternetAddressへとセットされるので、そこで例外が発生しますのでご注意下さい

定数アノテーションには以下が指定出来ます。

アノテーション 複数指定の可否
SUBJECT ×
FROM ×
TO
CC
BCC
REPLY_TO ×
RETURN_PATH ×

ここで設定された値は、Maiインタフェース名_メソッド名.diconで設定されたものより優先されます。

ただし、Subjectはテンプレートの1行目に書いたものが最優先となります。アノテーションで設定したい場合は、テンプレートの1行目の「Subject: 〜」を行ごと削除して下さい。1行目からメール本文が始まっても問題はありません。

メール内容クラスのプロパティでの設定

ここまでの方法ですと、FromやToなどのメール設定はビルド時に決まってしまい、アプリケーションで動的に設定する事が出来ません。S2Maiは、メールの内容を保持するクラスのプロパティを命名規則に準じた名前にする事で、そのプロパティの値を使ってメール設定を行います。アプリケーション側で、このプロパティに値をセットしてやる事で、動的に設定する事が可能となります。

ここでは、先程サンプルで使った「TestDto」にメール設定用プロパティを追加してみます。

s2mai.test.dto.TestDto
public class TestDto{
    private String name;
    
    private InternetAddress from;
    private List to;
    private MailAddress[] cc;
    private String[] bcc
    private String subject;
    
    (setter、getter省略)
}

そうすると、このプロパティに設定された値が、「Maiインタフェース名.dicon」または「Maiインタフェース名_メソッド名.dicon」の記述内容、Maiインタフェースに書いたアノテーションのどれよりも優先されて反映されます。

ただし、Subjectはテンプレートの1行目が「Subject: 〜」だった場合は、テンプレートが最優先です。

ここではさまざまな型でプロパティとして宣言されています。S2Maiで対応しているプロパティ名、変数型は下記になります。

プロパティ名 メール設定 指定可能な型
subject 件名 String
from From String
javax.mail.internet.InternetAddress
org.seasar.mai.mail.MailAddress
to To String
javax.mail.internet.InternetAddress
org.seasar.mai.mail.MailAddress
およびそれぞれの配列もしくはList
cc Cc String
javax.mail.internet.InternetAddress
org.seasar.mai.mail.MailAddress
およびそれぞれの配列もしくはList
bcc Bcc String
javax.mail.internet.InternetAddress
org.seasar.mai.mail.MailAddress
およびそれぞれの配列もしくはList
replyTo Reply-To String
javax.mail.internet.InternetAddress
org.seasar.mai.mail.MailAddress
returnPath Return-Path String
javax.mail.internet.InternetAddress
org.seasar.mai.mail.MailAddress

指定可能な型以外の場合はエラーにはなりませんが、nullが設定されます。また、fromなどを配列もしくはListにした場合は、最後の要素が反映されます(が、動作を保証するものではありません)。

Listの場合、要素の型がString、InternetAddress、MailAddress混在でも動作します。他に添付ファイル用のプロパティもありますが、それは後述します。

また、サーバの設定をmailProperties.diconで設定しましたが、メールの内容を保持するクラスからの設定も可能です。特定のメールのみSMTPホストを切り替えたい、などの要件がある場合にはこちらで設定します。

プロパティ名 サーバ設定 指定可能な型
host SMTPサーバ String
port SMTPポート String
Integer
int
username SMTPユーザー名 String
password SMTPパスワード String

添付ファイルについて

添付ファイルを扱う場合は、S2Maiで提供している「org.seasar.mai.mail.AttachedFile」を使います。

コンストラクタとして、下記が用意されています。

  1. AttachedFile(File file)
  2. AttachedFile(File file, String fileName)
  3. AttachedFile(InputStream inputStream, String fileName)
  4. AttachedFile(URL url, String fileName)

それぞれ第二引数でファイル名を設定しますが、適切な拡張子が必要となります。Fileのみを指定した場合は、そのファイル名がセットされます。

動作を保証するために、それぞれの設定値のsetterは用意していません。getterはあります。

「TestDto」に添付ファイルプロパティを追加しましょう。

s2mai.test.dto.TestDto
public class TestDto{
    private String name;
    
    private AttachedFile file;
    
    (setter、getter省略)
}

プロパティ名は何でも構いません。型がAttachedFileであれば添付ファイルと見なします。また、複数指定の場合は配列もサポートしています。さらに、プロパティを複数構えても大丈夫です。

public class TestDto{
    private String name;
    
    private AttachedFile file;
    private AttachedFile[] files;
    
    (setter、getter省略)
}

fileとfilesのそれぞれにセットされたファイルが添付されます。

また、型をListにした場合は、このままのプロパティ名ですと要素の型が不確定のため無視されますが、プロパティ名を「attachedFile」という名前にすれば、添付ファイルとして扱います。

public class TestDto{
    private String name;
    
    private List attachedFile;
    
    (setter、getter省略)
}

勿論、この「attachedFile」というプロパティ名は、Listに制限されるものではなく、単体のAttachedFileの場合でもその配列の場合でも付けて構いません。

ただし、ジェネリクスを用いた場合はこの規約を守らなくてもOKです。要素の型が保証されますので、プロパティ名は自由に付けられます。

public class TestDto{
    private String name;
    
    private List<AttachedFile> fileList;
    
    (setter、getter省略)
}

このジェネリクスのサポートを使いたい場合は、s2-tigerが必要です。詳細はこちらを参照して下さい。