struts2とseasar2を使ってアプリ作成(準備その1)

今回はstruts2-seasar-pluginを使ってS2JDBCでDB接続できるところまで確認します。
struts2-seasar-plugin

struts2でアプリ作成(準備編2)の続きです。

pom.xml

必要なライブラリは下記を参照してpom.xmlに追加します。
http://s2container.seasar.org/2.4/ja/setup.html

seasarのパッケージをmavenで取得する場合、pom.xmlレポジトリを追加する必要があります。下記を追加します。

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

続いて、dependenciesタグ内に下記を追加します。

    <dependency>
      <groupId>org.seasar.container</groupId>
      <artifactId>s2-framework</artifactId>
      <version>2.4.46</version>
    </dependency>
    <dependency>
      <groupId>org.seasar.container</groupId>
      <artifactId>s2-extension</artifactId>
      <version>2.4.46</version>
    </dependency>
    <dependency>
      <groupId>org.seasar.container</groupId>
      <artifactId>s2-tiger</artifactId>
      <version>2.4.46</version>
    </dependency>
    <dependency>
      <groupId>org.seasar.struts2</groupId>
      <artifactId>struts2-seasar-plugin</artifactId>
      <version>1.0.0</version>
      <exclusions>
        <exclusion>
          <groupId>opensymphony</groupId>
          <artifactId>xwork</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.apache.geronimo.specs</groupId>
      <artifactId>geronimo-jta_1.1_spec</artifactId>
      <version>1.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.geronimo.specs</groupId>
      <artifactId>geronimo-jpa_3.0_spec</artifactId>
      <version>1.0</version>
    </dependency>
    <dependency>
      <groupId>postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>9.1-901-1.jdbc4</version>
    </dependency>

s2-framework~s2-tigerはseasar2のコアとなる部分です。
s2-tigerだけをpom.xmlに追加しても他の二つを併せて取得してきますが、ここではあえて明記しています。
struts2-seasar-pluginはStruts2からS2Containerのコンポーネントを呼び出すライブラリです。
exclusionsタグが含まれますが、これを書かないと古いバージョンのxworkを取得して起動時に次のようなエラーが出ます。

致命的: フィルタ struts2 の起動中の例外です
java.lang.NoSuchMethodError: com.opensymphony.xwork2.config.ConfigurationManager.addContainerProvider(Lcom/opensymphony/xwork2/config/ContainerProvider;)V
	at org.apache.struts2.dispatcher.Dispatcher.init_FileManager(Dispatcher.java:336)
	at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:465)
	at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:74)
	at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(StrutsPrepareAndExecuteFilter.java:51)
	at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:295)
以下略

geronimo-はJ2EEの実装です。(詳細はapache本家やwikipediaを参照してください)
postgresqlpostgresql用のjdbcライブラリです。今回はpostgresqlを使用しますが、使用するRDBMSによって適当なライブラリを指定してください。

データベース

今回はpostgresqlを使用します。
バージョン: 9.1
ホスト: localhost
ポート: 5432
データベース名: myapp
ユーザ名: myapp
パスワード: なし
アクセス権等は正しく与えておく必要があります。

設定ファイル

ここを見ながら順に設定ファイルを作成していきます。
http://s2container.seasar.org/2.4/ja/stdDicon.html
http://s2container.seasar.org/2.4/ja/s2jdbc_setup.html
seasar2の設定ファイルは4つ。(src/main/resources)

  • app.dicon
  • convention.dicon
  • s2jdbc.dicon
  • jdbc.dicon

Seasar2では設定を.dicon拡張子のxmlファイルに記載していきます。
あとはweb.xmlにも設定を追加します。

app.dicon
<?xml version="1.0"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN" "http://www.seasar.org/dtd/components23.dtd">
<components>
  <include path="s2jdbc.dicon"/>
  <component class="kamegu.action.SeasarTestAction" instance="prototype"/>
</components>

ルートとなる設定ファイルです。
s2jdbc.diconは今回定義するdiconファイル。
SeasarTestActionは今回確認用に作成する画面のアクションクラス。
instance属性を指定しない場合、singletonでインスタンスが作成されてしまうため、prototype(毎回newする)に設定します。
なお、この形だと画面ごとにcomponentを追加する必要があります。

convention.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" 
	"http://www.seasar.org/dtd/components24.dtd">
<components>
	<component class="org.seasar.framework.convention.impl.NamingConventionImpl">
		<initMethod name="addRootPackageName">
			<arg>"kamegu"</arg>
		</initMethod>
	</component>
	<component class="org.seasar.framework.convention.impl.PersistenceConventionImpl"/>
</components>

SMART-deployで使用されるもののようだが、s2jdbc-internal.dicon(s2jdbc.diconで使用)で使用されているので作成しておく必要あり。
addRootPackageNameの中身だけを書き換えればとりあえずはOKっぽい。

jdbc.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
    "http://www.seasar.org/dtd/components24.dtd">
<components namespace="jdbc">
    <include path="jta.dicon"/>
    <include path="jdbc-extension.dicon"
        condition="@org.seasar.framework.util.ResourceUtil@isExist('convention.dicon')"/>

    <component class="org.seasar.extension.jdbc.impl.BasicResultSetFactory"/>
    <component class="org.seasar.extension.jdbc.impl.ConfigurableStatementFactory">
        <arg>
            <component class="org.seasar.extension.jdbc.impl.BasicStatementFactory"/>
        </arg>
        <property name="fetchSize">100</property>
    </component>

    <!-- for PostgreSQL -->
    <component name="xaDataSource" class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
        <property name="driverClassName">"org.postgresql.Driver"</property>
        <property name="URL">"jdbc:postgresql://localhost/myapp"</property>
        <property name="user">"myapp"</property>
        <property name="password">""</property>
    </component>

    <component name="connectionPool"
        class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
        <property name="timeout">600</property>
        <property name="maxPoolSize">10</property>
        <property name="allowLocalTx">true</property>
        <destroyMethod name="close"/>
    </component>
    <component name="dataSource"
        class="org.seasar.extension.dbcp.impl.DataSourceImpl"/>
</components>

DB接続先設定です。
seasar2のzipファイルを本家からダウンロードすると、jdbc.diconファイルがあるのでそれをもとに接続先の設定を行って要らないところ(コメントアウトされている部分)を削ったものが上の内容です。

s2jdbc.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
    "http://www.seasar.org/dtd/components24.dtd">
<components>
    <include path="jdbc.dicon"/>
    <include path="s2jdbc-internal.dicon"/>
    <component name="jdbcManager" class="org.seasar.extension.jdbc.manager.JdbcManagerImpl">
        <property name="maxRows">0</property>
        <property name="fetchSize">0</property>
        <property name="queryTimeout">0</property>
        <property name="dialect">postgre81Dialect</property>
        <property name="allowVariableSqlForBatchUpdate">true</property>
    </component>
</components>

S2Tiger-2.4.x.zipを解凍してできたs2-tigerのsrc/test/resourcesにあるs2jdbc.diconをコピーしてdialectの中身を書き換えます。
指定する文字列は下記を参照。
http://s2container.seasar.org/2.4/ja/s2jdbc_setup.html

web.xml
  <listener>
    <listener-class>org.seasar.framework.container.servlet.S2ContainerListener</listener-class>
  </listener>

上記を追加します。

テーブル作成、エンティティ作成

employeeテーブルを作成(postgresql)、データ追加
create table employee (
  id SERIAL NOT NULL, 
  name TEXT NOT NULL
);
insert into employee (name) 
values ('hogeo'),('hogetaro');
src/main/java/kamegu/entity/Employee.java
package kamegu.entity;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Employee {
	@Id
	public Integer id;

	public String name;
}

エンティティの作成についてはこちらを参照
http://s2container.seasar.org/2.4/ja/s2jdbc_entity.html
nameフィールドの@Columnアノテーションは省略しています。

確認画面作成

src/main/java/kamegu/action/SeasarTest.java
package kamegu.action;

import java.util.List;
import kamegu.entity.Employee;
import org.seasar.extension.jdbc.JdbcManager;
import com.opensymphony.xwork2.ActionSupport;

public class SeasarTestAction extends ActionSupport {
	public List<Employee> employees;
	public String message1 = "seasar testです";
	public JdbcManager jdbcManager;

	@Override
	public String execute() throws Exception {
		employees = jdbcManager.from(Employee.class).getResultList();
		return SUCCESS;
	}
}

このアクションクラス自体はapp.diconでコンポーネントとして登録されています(instance=prototype)。
jdbcManagerはs2jdbc.diconでコンポーネント登録されています(instance=singleton)。
つまり、リクエストがあるごとにSeasarTestActionはnewされ、singletonで作成されているjdbcManagerがセットされます。

src/main/wabapp/WEB-INF/content/seasar-test.jsp
<%@page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf8">
</head>
<body>
Seaser Test画面です<br>
<s:property value="message1"/>
<br>

<ul>
<s:iterator value="employees">
  <li><s:property value="name"/></li>
</s:iterator>
</ul>
</body>
</html>

起動、動作確認

以上の設定でサーバを起動し、myapp/seasar-testにアクセスすると、テーブルに追加されているデータの一覧が表示されればOKです。

続き

なお、以下のようなメッセージがコンソールに表示されました。

警告: kamegu.action.SeasarTestActionのプロパティ(container)が見つからないので設定をスキップします

これの対応と、app.diconに毎回アクションをcomponentとして登録しなくするための設定は次回に回します。
(長くなったので)