2008/03/12からのアクセス回数 8975
Formコントローラでエラーをチェックする場合、
しかし、ドメインモデルのString型以外の属性に不適当な文字列を指定するとValidationの前の 段階でエラーとなり、Validation機能が有効に働きません。
以下は、MemberクラスにInteger型のageを追加し、入力として数値としてふさわしくない"b" を入力したときのエラー出力画面です。
GenMVCプラグインで実行したいと考えているプログラミングは、
という一連の流れにおいて、ドメインモデルの属性の型にStringしか使えないというのは 致命的な問題です。
悩んだあげく以下のような方法で対応することにしました。
idを除くテーブル要素となる属性(テーブルのカラムに対応するもの)の型をすべてString型とし、 それ以外をそのままの型と持ち、それらのアクセスメソッドを生成します。
Cart問題のLineItemを定義しますと、
public class LineItem { private Integer id; private Integer quantity = new Integer(1); private Integer productId; private Product product; private Integer orderId; -- アクセスメソッドは省略 }
から以下のようなコマンドオブジェクトが生成されます。
package example.cart.command; public class LineItemCommand { private Integer id; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } private String orderId; public String getOrderId () { return orderId; } public void setOrderId (String orderId) { this.orderId = orderId; } -- productId, quantity は、省略 private example.cart.domain.Product product; public example.cart.domain.Product getProduct () { return product; } public void setProduct (example.cart.domain.Product product) { this.product = product; } }
先ほどのLineItemの編集を行うEditLineItemControllerを見てみると
protected void bind(Object target, Object source) throws Exception { CustomDataBinder binder = new CustomDataBinder(target, source); this.prepareBinder(binder); binder.bind(); } protected Object commandToDomain(Object source) throws Exception { Object object = new LineItem(); bind(object, source); return (object); } protected Object domainToCommand(Object source) throws Exception { Object object = new LineItemCommand(); bind(object, source); return (object); }
このように簡単にコマンドオブジェクトとドメインモデルの属性間の値変換ができるのは、 ServletRequestDataBinderとCustomDataBinderのおかげです。
CustomDataBinderでは、
以下にCustomDataBinderのソースを示します。
package jp.co.pwv.utils; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.sql.Date; import java.sql.Timestamp; import java.util.HashMap; import java.util.List; import java.util.Map; import jp.co.pwv.utils.DbHelper; import org.springframework.beans.MutablePropertyValues; import org.springframework.web.bind.ServletRequestDataBinder; public class CustomDataBinder extends ServletRequestDataBinder { DbHelper helper; Map valueMap = new HashMap(); private void setUpValueMap(Object source) { List propList = helper.getPropList(); for (int i = 0; i < propList.size(); i++) { PropertyDescriptor objProp = (PropertyDescriptor)propList.get(i); String propName = objProp.getName().toUpperCase(); Class propType = objProp.getPropertyType(); Method getMethod = objProp.getReadMethod(); Object propValue = null; try { propValue = getMethod.invoke(source, null); } catch (Exception e) { propValue = null; } if (propName.equals("CLASS")) // オブジェクト自身を除く continue; if (propValue != null) if (Integer.class.equals(propType) || Double.class.equals(propType) || Boolean.class.equals(propType) || String.class.equals(propType) || Date.class.equals(propType) || java.util.Date.class.equals(propType) || Timestamp.class.equals(propType)) { valueMap.put(objProp.getName(), propValue.toString()); } else { valueMap.put(objProp.getName(), propValue); } } } public CustomDataBinder(Object target, Object source) { super(target); helper = new DbHelper(source.getClass()); setUpValueMap(source); } public void bind() throws Exception { MutablePropertyValues mpvs = new MutablePropertyValues(); mpvs.addPropertyValues(valueMap); super.doBind(mpvs); } }
validation.xmlのmemberCommandのフォームのageのチェックをrequired,integerに変更します。
<form name="memberCommand"> <field property="address" depends="required"> <arg0 key="member.address" /> </field> <field property="age" depends="required,integer"> <arg0 key="member.age" /> </field> <field property="name" depends="required"> <arg0 key="member.name" /> </field> </form>
mavenでパッケージ、jettyを起動します。
$ mvn package $ mvn jetty:run
正常に動作し、"Member age must be an integer"のメッセージが出力しました。
この記事は、
皆様のご意見、ご希望をお待ちしております。