連載
» 2004年09月28日 10時00分 公開

JavaTips 〜Apache/Jakarta編:リクエストデータをJavaBeansにセット(Commons活用)

[BULL,@IT]

JavaBeansのプロパティを文字列として指定

 Javaで記述されたコンポーネント間で、まとまった情報をやり取りしたい場合は、JavaBeansを使用すると便利です。JavaBeansのプロパティxxxに値をセットしたり取得したりするには、setXxx()やgetXxx()メソッドを呼ぶコードを記述します。しかし、XML形式の設定ファイル内に、JavaBeansにセットしたいプロパティ名と値の組が記述されていた場合等、アクセスしたいプロパティのプロパティ名を文字列として指定したい場合があります。このようなときは、java.lang.reflectパッケージによるリフレクションを用いて、プロパティ文字列に対応するsetter/getterメソッドを呼ぶコードを記述するのが一般的ですが、リフレクションを使用したコードは記述が大変で読みにくく、保守性が低くなるという問題があります。この問題はBeanUtilsを用いると解決します。

BeanUtilsの概要

 BeanUtilsは、Jakarta Commonsプロジェクトの産物であり、JavaBeansを容易に扱えるようにするためのユーティリティです。

 BeanUtilsのダウンロードはhttp://jakarta.apache.org/commons/beanutils/から行えます。執筆時点の最新版はバージョン1.5です。また、実行にはJakarta Commons Logging(http://jakarta.apache.org/commons/logging/からダウンロード可能)のcommons-logging.jarも必要です。ダウンロードしたzipファイルを展開して出てきたcommons-beanutils.jar、およびcommons-logging.jar双方にクラスパスに通すことでjavaコードから使用可能になります。

BeanUtilsを用いてJavaBeansのプロパティを文字列で指定しアクセスする

 BeanUtilsに含まれるorg.apache.commons.beanutils.PropertyUtilsBeanクラスを用いると、アクセスしたいプロパティを文字列として指定することができ、しかもリフレクションを用いた場合よりもコードの記述性や見通しが良くなります。さらに、PropertyUtilsBeanには以下のような機能もあります。

  • あるJavaBeansのプロパティaに格納された値が別のJavaBeansになっている場合、ネストしたJavaBeansのプロパティbを「a.b」のように文字列として指定し、直接アクセスする
  • プロパティcに格納された値が配列である場合、配列のn番目の要素を「c[2]」(n=2の場合)のように文字列として指定し、直接アクセスする
  • プロパティdに格納された値がMapである場合、あるキーを持つ要素を「d(somekey)」(キーがsomekeyの場合)のように文字列として指定し、直接アクセスする
  • 2つのJavaBeansのインスタンス同士で共通するプロパティ名の内容をコピーする

 これらの機能をリフレクションを用いて実装するのはとても大変ですが、BeanUtilsのPropertyUtilsBeanでは簡単に使用することができます。

 プロパティ名を文字列として指定し、プロパティにアクセスするにはPropertyUtilsBean#setProperty、PropertyUtilsBean#getPropertyを使用します。2つのJavaBeansのインスタンス同士で共通するプロパティ名の内容をコピーするにはPropertyUtilsBean#copyPropertiesを使用します。

 SampleBeanとSampleBean2というJavaBeansのインスタンスに対して、BeanUtilsを用いてプロパティにアクセスする例をBeanUtilsSample.javaに示します。配列のインデックスやMapのキーを文字列で指定することで、プロパティに格納された配列やMapインスタンス内の1要素に簡単にアクセスできていることが分かります。

SampleBean.java
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

public class SampleBean implements Serializable {
    public class InnerClass {
        private String message;
        public String getMessage() { return this.message; }
        public void setMessage(String message) { 
            this.message = message; 
        }
    }

    private String foo;
    private Integer[] intarray = new Integer[3];
    private Map table = new HashMap();
    private InnerClass inner = new InnerClass();

    public void setFoo(String foo) { this.foo = foo; }
    public String getFoo() { return this.foo; }
    public void setIntarray(Integer[] intarray) { 
         this.intarray = intarray; 
    }
    public Integer[] getIntarray() { return this.intarray; }
    public void setInner(InnerClass inner) { this.inner = inner; }
    public InnerClass getInner() { return this.inner; }
    public void setTable(Map table) { this.table = table;    }
    public Map getTable() { return this.table; }
}


SampleBean2.java
import java.io.Serializable;

public class SampleBean2 implements Serializable {
   private String foo;

    public void setFoo(String foo) { this.foo = foo; }
    public String getFoo() { return this.foo; }
}


BeanUtilsSample.java
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.PropertyUtilsBean;

public class BeanUtilsSample {
  public static void main(String[] args) {
    try {
      SampleBean bean = new SampleBean();
      SampleBean2 bean2 = new SampleBean2();
      PropertyUtilsBean util = new PropertyUtilsBean();

      // fooプロパティにアクセス
      util.setProperty(bean, "foo", "bar");
      System.out.println((String)util.getProperty(bean, "foo"));

      // innerプロパティに格納されたJavaBeansのmessage
      // プロパティに直接アクセス
      util.setProperty(bean, "inner.message", "foobar");
      System.out.println((String)util.getProperty(bean
                                          , "inner.message"));

      // intarrayプロパティに格納された配列の1番目の要素にアクセス
      util.setProperty(bean, "intarray[1]", new Integer(1234));
      System.out.println((Integer)util.getProperty(bean
                                          , "intarray[1]"));

      // tableプロパティに格納されたMapインスタンスの
      // キーhogeで参照される要素にアクセス
      util.setProperty(bean, "table(hoge)", "fuga");
      System.out.println((String)util.getProperty(bean
                                          , "table(hoge)"));

      System.out.println("----");
      
      // beanの全プロパティのうち、bean2にも存在する
      // プロパティに値をコピー
      // この例ではfooプロパティの値がコピーされる
      util.copyProperties(bean2, bean);
      System.out.println((String)util.getProperty(bean2, "foo"));
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    }
  }
}


実行結果
bar
foobar
1234
fuga
----
bar


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。