[Seasar-user:3473] 自作のページャーを動作させたい

[E-MAIL ADDRESS DELETED] [E-MAIL ADDRESS DELETED]
2006年 4月 7日 (金) 21:05:39 JST


関です。

初めて投稿いたします。

S2JSFが期待通りに動作しませんので、お気づきの点があれば教えていただきたいと思っています。
長文になってしまいすみませんが、他に聞く場所もないようなのでこちらにお送りさせていただきました。

環境
- JDK 1.5.0.06
- Tomcat 5.5.15
- Seaser 2.3.7
- S2Dao 1.0.31
- MySQL 5.0.18

■概要
ページャー機能を実装したページを作成したいと考えています。
その時、DAOに付属するPager用のJSPを利用しないで、JSFのみで実現したいです。

私の考える実装方法ですが、
1.検索画面でConditionDtoに検索条件を格納します。
  (この時、OFFSETとLIMITを、input type="hedden"でセット、表示するページはpageIndexとして初期値は0)
2.ConditionDtoを使用してSQLを実行し、結果のArrayListをActionImplのLogicから取得します。(=ResultList)
3.再度同じ条件でSQLを実行し、今度はConditionDtoに設定したLIMITなら
  何ページになるかをArrayList形式で取得します。(=PagerList)
  (Ex:2.の検索結果が10件で、LIMITが3を設定している場合、ArrayListに4個値を入れて返す)
4.HTML側で3.のPagerListをs:forEachしてAタグを繰り返し生成する。
  (この時にConditionDtoの内容をパラメータで埋め込んでおく)
5.Aタグを埋め込む際、pageIndexだけインクリメントして、クリックすればどのページに行くかを設定しておく
6.最後にデータ表示部分でResultListをs:forEachで出力する。

■問題点
Eclipseのデバックモードで処理を見ると検索画面で登録したConditionDtoの値が
PagerListのリンクをクリックして
Actionを実行する際に、ConditionDtoにSetされません。
(Seasarの中までは理解できないので追えません)

■聞きたい事
1.そもそも、上記の概要に書いてある方法にてページャーは実装できるのか?
2.どこらへんが間違っていそうか?

どなたか原因が分かる方がおられましたら
ご返事頂ければと思います。

JAVAの勉強のために本屋で青い本を手に取ってから1ヶ月ほどはまっております。
フレームワークの概念から理解していなかったために、まだまだ機能を理解できていませんが、
よろしくお願い致します。

** 以下、サンプルプログラムのソースコードになります。**

==============================
ファイル構成
*がディレクトリ
==============================
*project
 *html
  test-input.html
  test-result.html
 *WEB-INF
  *src
   *jsf
    *action
     *impl
      EmployeeActionImpl.java
     EmployeeAction.java
    *dao
     EmployeeDao.java
    *dicon
     employee.dicon
    *Entity
     Employee.java
    *login
     *impl
      EmployeeLogicImpl.java
     EmployeeLogic.java
    app.dicon
    dao.dicon
    j2ee.dicon
    jsf.dicon





=========================================
test-input.html
=========================================
<html xmlns:m="http://www.seasar.org/maya">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>検索画面</title>
</head>
<body>
	<span m:inject="f:param" m:name="layoutTitle" m:value="検索画面"/>

	<span m:inject="s:insert" m:name="content">
		<form>
			<table>
				<tr>
					<td>
						開始日:<input
							type="text"
							m:value="#{employeeConditionDto.startDate}"
							id="startDate"
							value="startDate"/>
					</td>
				</tr>
				<tr>
					<td>
						終了日:<input type="text"
							m:value="#{employeeConditionDto.endDate}"
							id="endDate"
							value="endDate"/>
					</td>
				</tr>
				<tr>
					<td>
						レンジ:<input type="text"
							m:value="#{employeeConditionDto.range}"
							id="range"
							value="range"/>
					</td>
				</tr>
				<tr>
					<td>
						ページ:<input type="text"
							m:value="#{employeeConditionDto.pageIndex}"
							id="pageIndex"
							value="pageIndex"/>
					</td>
				</tr>
				<tr>
					<td>
						<input type="button"
							value="閲覧"
							m:action="#{employeeAction.view}" />
					</td>
				</tr>
			</table>

		</form>

	</span>
</body>
</html>


=========================================
test-result.html
=========================================
<html xmlns:m="http://www.seasar.org/maya">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>結果画面</title>
</head>
<body>
	<span m:inject="f:param" m:name="layoutTitle" m:value="結果画面"/>

	<span m:inject="s:insert" m:name="content">
		<form>
			<!-- #ページャー生成# -->
			<div>
			【Pager:
		    <span m:inject="s:forEach" m:items="#{pagerList}" m:var="e" m:varIndex="i">
			    (<a href="#" m:action="#{employeeAction.view}">
			    	<span											m:value="#{i+1}">#</span>
			    	<span m:inject="f:param" m:name="pageIndex"		m:value="#{i}"></span>
			    	<span m:inject="f:param" m:name="startDate" 	m:value="#{employeeConditionDto.startDate}"/>
			    	<span m:inject="f:param" m:name="endDate" 		m:value="#{employeeConditionDto.endDate}"/>
			    	<span m:inject="f:param" m:name="range" 		m:value="#{employeeConditionDto.range}"/>
			    </a>)
		    </span>
			】
			</div>

			<!-- #データ表示# -->
		<table border="1">
			    <tr>
			        <th>コード</th>
			        <th>氏名</th>
			        <th>アクション</th>
			    </tr>
		    <span m:inject="s:forEach" m:items="#{employeeList}" m:var="e" m:varIndex="i">
			    <tr>
			    	<td><span m:value="#{e.Employee_Code}">0000</span></td>
			    	<td><span m:value="#{e.Employee_Code}">シーサー太郎</span></td>
			    	<td>[<a m:action="employeeAction.select">action</a>]</td>
			    </tr>
		    </span>
		</table>
		<br/>
		</form>
	</span>
</body>
</html>

=========================================
employee.dicon
一連の流れで使用するコンポーネントを宣言しています。
pagerList	--	何ページあるかのリスト
employeeConditionDto	--	検索条件
employeeList	--	検索結果のリスト
=========================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
	"http://www.seasar.org/dtd/components21.dtd">
<components>

	<include path="j2ee.dicon"/>
	<include path="dao.dicon"/>

	<!-- DTO -->
	<component name="pagerList" 			class="jsf.dto.PagerList" 				instance="session"/>
	<component name="employeeConditionDto" 	class="jsf.dto.EmployeeConditionDto" 	instance="session"/>
	<component name="employeeList" 			class="jsf.dto.EmployeeList" 			instance="session"/>

	<!-- ACTION-LOGIC -->
	<component name="employeeAction" 	class="jsf.action.impl.EmployeeActionImpl" 	instance="session"/>
	<component class="jsf.logic.impl.EmployeeLogicImpl" />

	<!-- DAO -->
 	<component class="jsf.dao.EmployeeDao">
 		<aspect>interceptor</aspect>
 	</component>

</components>



=========================================
EmployeeAction.java
検索画面から結果ページへ行くメソッドと
結果ページのアイテムをクリックして何か処理を行うメソッドを定義します(今回無関係)
=========================================
package jsf.action;

public interface EmployeeAction {
	public String view();
	public String select();
}

=========================================
EmployeeActionImpl.java
検索画面から結果ページへ行くメソッドと
結果ページのアイテムをクリックして何か処理を行うメソッドの実装です。
=========================================
package jsf.action.impl;

import jsf.action.EmployeeAction;
import jsf.dto.EmployeeConditionDto;
import jsf.dto.EmployeeList;
import jsf.dto.PagerList;
import jsf.logic.EmployeeLogic;

public class EmployeeActionImpl implements EmployeeAction {

	private EmployeeConditionDto	employeeConditionDto;
	private	EmployeeList			employeeList;
	private EmployeeLogic			employeeLogic;
	private PagerList				pagerList;

	public EmployeeActionImpl() {

	}

	public String view() {
		employeeList	= employeeLogic.getEmployeeList(employeeConditionDto);
		pagerList		= employeeLogic.getEmployeeListPager(employeeConditionDto);

		return "test-result";
	}

	public String select() {

		return null;
	}

	public EmployeeConditionDto getEmployeeConditionDto() {
		return employeeConditionDto;
	}

	public void setEmployeeConditionDto(EmployeeConditionDto employeeConditionDto) {
		this.employeeConditionDto = employeeConditionDto;
	}

	public EmployeeList getEmployeeList() {
		return employeeList;
	}

	public void setEmployeeList(EmployeeList employeeList) {
		this.employeeList = employeeList;
	}

	public EmployeeLogic getEmployeeLogic() {
		return employeeLogic;
	}

	public void setEmployeeLogic(EmployeeLogic employeeLogic) {
		this.employeeLogic = employeeLogic;
	}

	public PagerList getPagerList() {
		return pagerList;
	}

	public void setPagerList(PagerList pagerList) {
		this.pagerList = pagerList;
	}

}

=========================================
EmployeeLogic.java
結果ページに出力するための結果リストを取得するメソッドと
ページャーのリストを取得するメソッドがあります。
=========================================
package jsf.logic;

import jsf.dto.EmployeeConditionDto;
import jsf.dto.EmployeeList;
import jsf.dto.PagerList;

public interface EmployeeLogic {

	public EmployeeList getEmployeeList(EmployeeConditionDto employeeConditionDto);
	public PagerList getEmployeeListPager(EmployeeConditionDto employeeConditionDto);

}

=========================================
EmployeeLogicImpl.java
結果ページに出力するための結果リストを取得するメソッドと
ページャーのリストを取得するメソッドの実装です。
=========================================
package jsf.logic.impl;

import java.text.SimpleDateFormat;
import java.util.List;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;
import jsf.dao.EmployeeDao;
import jsf.dto.EmployeeConditionDto;
import jsf.dto.EmployeeList;
import jsf.dto.PagerList;
import jsf.logic.EmployeeLogic;


public class EmployeeLogicImpl implements EmployeeLogic {


	public EmployeeList getEmployeeList(EmployeeConditionDto employeeConditionDto) {

		String path = "jsf/dicon/employee.dicon";

		S2Container container = S2ContainerFactory.create(path);
		container.init();

		List resultList = null;

//		 ページャ対応の検索を実行
		EmployeeDao dao	= (EmployeeDao)container.getComponent(EmployeeDao.class);
		String sDate 	= new SimpleDateFormat("yyyy/MM/dd").format(employeeConditionDto.getStartDate()) ;
		String eDate 	= new SimpleDateFormat("yyyy/MM/dd").format(employeeConditionDto.getEndDate()) ;
		int offset			= employeeConditionDto.getRange() * (employeeConditionDto.getPageIndex() );
		int limit			= employeeConditionDto.getRange();

		resultList = dao.selectEmployee(sDate, eDate, offset, limit);

		EmployeeList employeeList = new EmployeeList( resultList );

		return employeeList;
	}

	public PagerList getEmployeeListPager(EmployeeConditionDto employeeConditionDto) {

		String path = "jsf/dicon/employee.dicon";

		S2Container container = S2ContainerFactory.create(path);
		container.init();

		List resultList = null;

//		 ページャ対応の検索を実行
		EmployeeDao dao	= (EmployeeDao)container.getComponent(EmployeeDao.class);
		String sDate 		= new SimpleDateFormat("yyyy/MM/dd").format(employeeConditionDto.getStartDate()) ;
		String eDate 		= new SimpleDateFormat("yyyy/MM/dd").format(employeeConditionDto.getEndDate()) ;

		resultList = dao.selectEmployeePager(sDate, eDate);

		// ここからページャーアイテム
		System.out.println("record number:" + resultList.size() );
		int page = resultList.size() / employeeConditionDto.getRange();

		if ( (resultList.size() % employeeConditionDto.getRange()) > 0){
			page++;
		}

		PagerList pageList = new PagerList();

		for (int i = 0; i < page; i++) {
			pageList.add(i);
		}
		return pageList;
	}
}

=========================================
EmployeeDao.java
ページ部分だけ返すSQLと、全部のデータを返すSQLの2種類があります。
=========================================
package jsf.dao;

import java.util.List;

import jsf.entity.Employee;

public interface EmployeeDao {

	public Class BEAN = Employee.class;

	/* ページャー用 一部抜き出しSQL */
	public List selectEmployee(String startDate, String endDate, int offset, int limit);
	public static final String selectEmployee_ARGS = "startDate,endDate,offset,limit";
	public static final String selectEmployee_SQL =
		"SELECT * " +
		"FROM Employee " +
		"WHERE Initiation_Date between /*startDate*/'2006/03/20' and /*endDate*/'2006/03/23' " +
		"LIMIT /*offset*/0 ,/*limit*/5";

	/* ページャー用 全部抜き出しSQL countした方が良いかも */
	public List selectEmployeePager(String startDate, String endDate);
	public static final String selectEmployeePager_ARGS = "startDate,endDate";
	public static final String selectEmployeePager_SQL =
		"SELECT * " +
		"FROM Employee " +
		"WHERE Initiation_Date between /*startDate*/'2006/03/20' and /*endDate*/'2006/03/23' ";

}



=========================================
Employee.java
DBのテーブル定義そのまま
=========================================
package jsf.entity;

import java.io.Serializable;
import java.util.Date;

public class Employee implements Serializable  {

	private static final long serialVersionUID = 1L;

	public static final String TABLE = "srt.Employee";

	private long Row_Id;
	private String Employee_Code;
	private String Employee_Name;
	private Date Insert_Date;
	private Date Update_Date;

	public Date getInsert_Date() {
		return Insert_Date;
	}
	public void setInsert_Date(Date insert_Date) {
		Insert_Date = insert_Date;
	}
	public Date getUpdate_Date() {
		return Update_Date;
	}
	public void setUpdate_Date(Date update_Date) {
		Update_Date = update_Date;
	}
	public String getEmployee_Code() {
		return Employee_Code;
	}
	public void setEmployee_Code(String employee_Code) {
		Employee_Code = employee_Code;
	}
	public String getEmployee_Name() {
		return Employee_Name;
	}
	public void setEmployee_Name(String employee_Name) {
		Employee_Name = employee_Name;
	}
	public long getRow_Id() {
		return Row_Id;
	}
	public void setRow_Id(long row_Id) {
		Row_Id = row_Id;
	}

}

=========================================
app.dicon
=========================================
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
	"http://www.seasar.org/dtd/components.dtd">
<components>
	<include path="jsf.dicon"/>
	<include path="dao.dicon"/>
	<include path="j2ee.dicon"/>
	<include path="jsf/dicon/employee.dicon"/>
</components>


=========================================
dao.dicon
ページャーを使用するバージョンのdao.diconを使用しています。
=========================================
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
	"http://www.seasar.org/dtd/components21.dtd">
<components namespace="dao">
	<include path="j2ee.dicon"/>
	<component
		name="annotationReaderFactory"
		class="org.seasar.dao.impl.FieldAnnotationReaderFactory"
	/>

	<component
		name="resultSetFactory"
		class="org.seasar.dao.pager.PagerResultSetFactoryWrapper">
		<arg>
			<component class="org.seasar.extension.jdbc.impl.BasicResultSetFactory"/>
		</arg>
		<property name="useScrollCursor">true</property>
	</component>
<!--
	<component
		name="resultSetFactory"
		class="org.seasar.dao.pager.PagerResultSetFactoryLimitOffsetWrapper">
		<arg>
			<component class="org.seasar.extension.jdbc.impl.BasicResultSetFactory"/>
		</arg>
		<arg>j2ee.dataSource</arg>
	</component>
-->
	<component
		class="org.seasar.dao.impl.DaoMetaDataFactoryImpl">
		<arg>j2ee.dataSource</arg>
		<arg>
			<component class="org.seasar.dao.pager.PagerStatementFactory"/>
		</arg>
<!--
		<arg>
			<component class="org.seasar.extension.jdbc.impl.BasicStatementFactory"/>
		</arg>
-->
		<arg>resultSetFactory</arg>
		<arg>annotationReaderFactory</arg>
	</component>

	<component name="interceptor"
		class="org.seasar.dao.pager.PagerS2DaoInterceptorWrapper">
		<arg>
			<component name="s2dao"
				class="org.seasar.dao.interceptors.S2DaoInterceptor">
			</component>
		</arg>
	</component>

<!--
	<component
		class="org.seasar.dao.impl.DaoMetaDataFactoryImpl"/>
	<component name="interceptor"
		class="org.seasar.dao.interceptors.S2DaoInterceptor"/>
-->
</components>
=========================================
j2ee.dicon
DB記述のみ変更しています。
=========================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">
<components namespace="j2ee">

	<component name="transactionManager"
		class="org.seasar.extension.jta.TransactionManagerImpl"/>
	<component name="requiredTx"
		class="org.seasar.extension.tx.RequiredInterceptor"/>
	<component name="requiresNewTx"
		class="org.seasar.extension.tx.RequiresNewInterceptor"/>
	<component name="mandatoryTx"
		class="org.seasar.extension.tx.MandatoryInterceptor"/>
	<component name="notSupportedTx"
		class="org.seasar.extension.tx.NotSupportedInterceptor"/>

	<component class="org.seasar.extension.jdbc.impl.BasicResultSetFactory"/>
	<component class="org.seasar.extension.jdbc.impl.BasicStatementFactory"/>

	<component name="xaDataSource"
		class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
		<property name="driverClassName">
			"com.mysql.jdbc.Driver"
		</property>
		<property name="URL">
			"jdbc:mysql://localhost/srt"
		</property>
		<property name="user">"root"</property>
		<property name="password">"password"</property>
	</component>

	<component name="dataSource"
		class="org.seasar.extension.dbcp.impl.DataSourceImpl">
		<arg>connectionPool</arg>
	</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>

</components>

=========================================
jsf.dicon
変更してません
=========================================

省略

=========================================
DBのテーブル定義
スキーマがsrt、文字コードがutf8
=========================================

DROP TABLE IF EXISTS `srt`.`employee`;
CREATE TABLE  `srt`.`employee` (
  `Row_Id` int(10) unsigned NOT NULL auto_increment,
  `Employee_Code` varchar(10) NOT NULL default '',
  `Employee_Name` varchar(10) NOT NULL default '',
  `Initiation_Date` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`Row_Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

=========================================
サンプルデータ作成
=========================================

INSERT INTO employee VALUES(1, '0001', 'A', '2006-01-01 00:00:00');
INSERT INTO employee VALUES(2, '0002', 'B', '2006-01-02 00:00:00');
INSERT INTO employee VALUES(3, '0003', 'C', '2006-01-03 00:00:00');
INSERT INTO employee VALUES(4, '0004', 'D', '2006-01-04 00:00:00');
INSERT INTO employee VALUES(5, '0005', 'E', '2006-01-05 00:00:00');
INSERT INTO employee VALUES(6, '0006', 'F', '2006-01-06 00:00:00');
INSERT INTO employee VALUES(7, '0007', 'G', '2006-01-07 00:00:00');
INSERT INTO employee VALUES(8, '0008', 'H', '2006-01-08 00:00:00');
INSERT INTO employee VALUES(9, '0009', 'I', '2006-01-09 00:00:00');
INSERT INTO employee VALUES(10, '0010', 'J', '2006-01-10 00:00:00');
INSERT INTO employee VALUES(11, '0011', 'K', '2006-01-11 00:00:00');
INSERT INTO employee VALUES(12, '0012', 'L', '2006-01-12 00:00:00');
INSERT INTO employee VALUES(13, '0013', 'M', '2006-01-13 00:00:00');
INSERT INTO employee VALUES(14, '0014', 'N', '2006-01-14 00:00:00');
INSERT INTO employee VALUES(15, '0015', 'O', '2006-01-15 00:00:00');
INSERT INTO employee VALUES(16, '0016', 'P', '2006-01-16 00:00:00');
INSERT INTO employee VALUES(17, '0017', 'Q', '2006-01-17 00:00:00');
INSERT INTO employee VALUES(18, '0018', 'R', '2006-01-18 00:00:00');
INSERT INTO employee VALUES(19, '0019', 'S', '2006-01-19 00:00:00');
INSERT INTO employee VALUES(20, '0020', 'T', '2006-01-20 00:00:00');
INSERT INTO employee VALUES(21, '0021', 'U', '2006-01-21 00:00:00');
INSERT INTO employee VALUES(22, '0022', 'V', '2006-01-22 00:00:00');
INSERT INTO employee VALUES(23, '0023', 'W', '2006-01-23 00:00:00');
INSERT INTO employee VALUES(24, '0024', 'X', '2006-01-24 00:00:00');
INSERT INTO employee VALUES(25, '0025', 'Y', '2006-01-25 00:00:00');
INSERT INTO employee VALUES(26, '0026', 'Z', '2006-01-26 00:00:00');





Seasar-user メーリングリストの案内