【コラム】

Java API、使ってますか?

6 JavaBeansのプロパティを同期させるバインディングAPI

6/60

JSR 295: Beans Bindingとは

JSR 295は、複数のJavaBeansのプロパティを同期させるための標準的な方法を策定するために提案された。たとえば2つの異なるBeanオブジェクトBeanAとBeanBがあるとき、BeanAのプロパティが変更されたらそれが自動的にBeanBのプロパティにも反映されるようにするというものだ。とくにSwingアプリケーションを作成している場合などには、このような処理を必要とするケースがよく出てくる。ユーザがテキストフィールドに入力した値を、リアルタイムにテーブルコンポーネントの表示に反映させたい場合などがそれにあたる。

通常、このような同期を行うためには状態の変更を検知するいくつかのリスナを登録し、相互のプロパティを確認し合わなければならない。JSR 295の目的は、シンプルな手段でこれらプロパティの同期を実現できるようにすることである。

以下では、JSR 295が目指すようなバインディングを使用したらどのようなことが可能になるのかを、実際の動作例を示しながら紹介したい。

データバインディングフレームワークの例

JSR 295はまだ参照実装が公開されておらず利用することができないので、ここではすでに公開されている他のデータバインディングフレームワークを使って、その実行例を見てみようと思う。

SwingLabs Data Binding Framework

まず最初に紹介するのが、Java.netにあるSwingLabsプロジェクトから公開されている「SwingLabs Data Binding Framework」だ。SwingLabsプロジェクトはSwingのGUIツールキットを拡張する目的で開始され、さまざまな新しいSwingコンポーネントやGUIアプリケーションの開発ツールを提供している。その中で生まれたのが、Swingコンポーネントにおいてデータモデルの同期を実現するSwingLabs Data Binding Frameworkである。

ただし、JSR 295の標準化プロセスが開始されたことにともなってこのフレームワークの開発はすでに終了しているため、2005年以来バージョンアップは行われていないので注意が必要だ。

SwingLabs Data Binding FrameworkはSwingLabsのサイトにある「SwingX」プロジェクトの成果物に同梱されている。ライセンスはLGPLとなっている。ファイル(swinglabs-0.8.0-bin.zip)をダウンロードして解凍し、中に含まれている「swinglabs-0.8.0.jar」をクラスパスに追加して使用する。

リスト1は、SwingLabsを使用してJLabelとJTextFieldのデータを同期させたプログラムの例である。

リスト1 SwingLabsBindingSample.java - SwingLabs Data Binding Frameworkの使用例

package swinglabssample;

import java.awt.GridLayout;
import java.beans.IntrospectionException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.jdesktop.binding.JavaBeanDataModel;
import org.jdesktop.binding.swingx.BindingFactory;
import org.jdesktop.binding.swingx.LabelBinding;
import org.jdesktop.binding.swingx.TextBinding;

public class SwingLabsBindingSample {
    private TextBinding textBinding;
    
    public SwingLabsBindingSample() {
        try {
            JFrame frame = new JFrame("BindingSample");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel panel = new JPanel(new GridLayout(2,1));
            
            JTextField field = new JTextField();
            field.setBorder(new TitledBorder("Input:"));
            JLabel label = new JLabel("Hello SwingLabs!");
            label.setBorder(new TitledBorder("Text:"));
            
            // JLabelのtextプロパティをJTextFieldにバインド
            JavaBeanDataModel dataModel = new JavaBeanDataModel(label);
            BindingFactory factory = new BindingFactory();
            textBinding = (TextBinding)factory.createBinding(field, dataModel, "text");
            textBinding.pull();
            field.getDocument().addDocumentListener(new MyDocumentListener());
            
            panel.add(label);
            panel.add(field);
            frame.getContentPane().add(panel);
            frame.setSize(200, 150);
            frame.setVisible(true);
        } catch (IntrospectionException ex) {
            ex.printStackTrace();
        }
    }
    
    private class MyDocumentListener implements DocumentListener {
        public void insertUpdate(DocumentEvent e) {
            textBinding.push();
        }
        public void removeUpdate(DocumentEvent e) {
            textBinding.push();
        }
        public void changedUpdate(DocumentEvent e) {
        }        
    }
    
    public static void main(String[] args) {
        SwingLabsBindingSample sample = new SwingLabsBindingSample();
    }
}

JavaBeanDataModelクラスはSwingコンポーネントにJavaBeans形式のデータをバインディングするためのデータモデルクラスである。今回はJLabelのtextプロパティとJTextFieldを関連付けたいので、ここではJLabelオブジェクトからJavaBeanDataModelを作成している。

バインディングはBindingクラスを継承した各クラスによって行われる。そしてBindingオブジェクトはBindingFactoryクラスのcreateBinding()メソッドを使用して作成する。このメソッドに対象のSwingコンポーネント、データモデル、関連付けるプロパティを指定すれば、関係するコンポーネントのためのBindingオブジェクトが作成される。

あとはBindingクラスのpush()メソッドを呼び出せば、データモデルにコンポーネントの値が反映され、pull()メソッドを呼び出せば逆にデータモデルの値がコンポーネントに反映される。

JGoodies Binding

次に紹介するのは、Javaアプリケーションのユーザインタフェースに関連したツールを開発しているJGoodiesプロジェクトによる成果物のひとつ、「JGoodies Binding」だ。JGoodies BindingもSwingLabsのものと同様、Swingコンポーネントにおけるデータモデルの同期を実現するフレームワークである。BSD Licenseに基づいて公開されている。

JGoodies BindingはJGoodiesのプロジェクトサイトから入手することができる。ダウンロードしたファイルを解凍し、binding-1.3.1.jarをクラスパスに含めて使用する。

JGoodies Bindingを使用したプログラムの例をリスト2に示す。

リスト2 JGoodiesBindingSample.java - JGoodies Bindingの使用例

package jgoodiessample;

import com.jgoodies.binding.adapter.Bindings;
import com.jgoodies.binding.beans.BeanAdapter;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

public class JGoodiesBindingSample {
    
    public JGoodiesBindingSample() {
            JFrame frame = new JFrame("BindingSample");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel panel = new JPanel(new GridLayout(2,1));
            
            JTextField field = new JTextField();
            JLabel label = new JLabel("Hello JGoodies!");
            label.setBorder(new TitledBorder("Text:"));
            
            // JLabelのtextプロパティをJTextFieldにバインド
            BeanAdapter adapter = new BeanAdapter(label, true);
            Bindings.bind(field, adapter.getValueModel("text"), false);
            field.setBorder(new TitledBorder("Input:"));
            
            panel.add(label);
            panel.add(field);
            frame.getContentPane().add(panel);
            frame.setSize(200, 150);
            frame.setVisible(true);
    }
    
    public static void main(String[] args) {
        JGoodiesBindingSample sample = new JGoodiesBindingSample();
    }
}

プロパティの同期を行うにはまず対象となるコンポーネントを指定してBeanAdapterオブジェクトを生成する。BeanAdapterからはgetValueModel( )メソッドを使用することでバインドしたいプロパティのValueModelを取得できる。このValueModelとバインドするコンポーネントをBindingsクラスのbind( )メソッドに渡せば、2つのコンポーネントのプロパティが同期されるようになる。この例の場合、必要なリスナがすべて自動的にインストールされるため、同期はリアルタイムに行われる。JGoodiesにはほかにもさまざまな使い方があるが、詳細は付属のドキュメントを参照していただきたい。

上記の例で、Swingアプリケーションにおけるデータバインディングフレームワークの有用性が実感していただけただろうか。これを踏まえ、新しく開発されるJSR 295のコード例を見てみよう。

JSR 295のコード例

リスト3は、Swing開発者の一人であるScott Violet氏が自身のブログに掲載した、JSR 295を使用したのプログラムのコード例である。

リスト4 Scott Violet氏によるJSR 295を使用したのコード例

BindingContext context = new BindingContext();

List<Bug> bugs = ...;
Binding tableBinding = context.addBinding(bugs, null, bugTable, "elements");

context.bind();

まず、バインディングのためのコンテキストを生成する。そして実際のバインド定義はaddBinding()メソッドを使用して行う。bugsはバインドされる元となるオブジェクト、bugTableはバインドの対象となるコンポーネント、"elements"は実際にバインドされるプロパティを示している。

最後にbind()メソッドを呼び出すことで必要なリスナの登録などが全て実行されるとのことだ。これによってプロパティの同期はリアルタイムに行われるようになる。アプローチとしてはJGoodiesのほうに似ているが、JSR 295ではバインディング定義がコンテキストによって管理される。

同氏のブログにはほかにもいくつかのコード例が示されており、JSR 295ではさまざまな方法でバインディングを定義できることがわかる。JSFやJSPで使用されているような式言語を利用できる点も興味深い。同ブログではJava Web Startによって実行できるサンプルプログラムも掲載されているので、ぜひ実行してJSR 259の動作を確かめてもらいたい。

プロパティのバインディングを利用すれば、1つの変更が多くのオブジェクトに影響を与えるようなケースのコードをシンプルに記述できるようになる。それは今回示したSwingのプログラム例でも実感していただけるかと思う。JSR 295では利便性を重視したさまざまな機能が採り入れられるとのことなので、実装の登場に大いに期待したいところだ。

提供:毎日就職ナビ

会員登録はこちら

学生のための就職情報サイト「毎日就職ナビ」。6,000社以上の新卒採用情報が常時掲載され、社内の雰囲気が伝わる情報画面、さまざまな項目での会社検索、エントリーや説明会検索など、機能も充実。無料適職診断、就活Q & A、エントリーシート添削講座など、就職活動に役立つ記事も満載です。研究者、エンジニアを目指す学生の方々も是非エントリーしてください。お待ちしています!

毎日コミュニケーションズはプライバシーマークを取得しています。

6/60

インデックス

連載目次
第60回 どうなる? 今後のJavaプラットフォーム(Java SE編)
第59回 どうなる? 今後のJavaプラットフォーム(Java EE編)
第58回 Java SE 7の要注目機能"クロージャ"はどうなるのか その6
第57回 Java SE 7の要注目機能"クロージャ"はどうなるのか その5
第56回 Java SE 7の要注目機能"クロージャ"はどうなるのか その4
第55回 Java SE 7の要注目機能"クロージャ"はどうなるのか その3
第54回 Java SE 7の要注目機能"クロージャ"はどうなるのか その2
第53回 Java SE 7の要注目機能"クロージャ"はどうなるのか
第52回 Early Draftが公開されたJSF 2.0
第51回 EJBから独立したJava Persistence 2.0
第50回 モバイルJavaの新しい潮流となるか - MSA 2.0のドラフト公開
第49回 やっぱり基本はServlet - Servlet 3.0のEarly Draftを読む
第48回 JOGLで3Dプログラミング その4
第47回 JOGLで3Dプログラミング その3
第46回 JOGLで3Dプログラミング その2
第45回 JOGLで3Dプログラミング
第44回 JARファイルを効率的にネットワーク転送するためのPack200形式
第43回 Early Draftで把握するEJB 3.1の新機能
第42回 次世代の携帯端末向けJava仕様"MIDP 3.0"はどうなるか その2
第41回 次世代の携帯端末向けJava仕様"MIDP 3.0"はどうなるか その1
第40回 リソースアダプタによる接続の仕組み
第39回 JCAを利用したシステム間接続
第38回 Java EEと外部システムの接続性を支えるJCAがバージョンアップ
第37回 Javaのモジュラリティ強化を担う"スーパーパッケージ"とは
第36回 JSR 308対応のコンパイラを試す
第35回 公開されたJSR 308のEarly Draftを検証する
第34回 スクリプト言語とJavaを結びつけるJSR 223
第33回 Java EE環境に統一されたコンポーネントモデルを提供するJSR 299 その2
第32回 Java EE環境に統一されたコンポーネントモデルを提供するJSR 299 その1
第31回 Javaの文法がそのまま使えるスクリプト言語"BeanShell"
第30回 Javaアプリケーションにオブジェクトのキャッシュ機構を提供するJCache API
第29回 Javaアプリケーションからのリソース管理を可能にするJSR 284
第28回 XMLデータソースへの問い合わせはJSR 225で
第27回 Portlet Specification 2.0をもっと手軽に利用する
第26回 次期Javaポートレット仕様となるJSR 286
第25回 JSFとポートレットをつなげるJSR 301
第24回 Webサービス向けのポートレット仕様「WSRP」
第23回 高い相互運用性を実現するポートレットAPI - JSR 168
第22回 Java EE環境でタスクのスケジューリングを可能にするJSR 236
第21回 Java EE環境でのスレッドプログラミングを可能にするJSR 237
第20回 音声認識/合成のためのAPI - Java Speech APIとJSR 113
第19回 JSR 291でJavaプラットフォームにダイナミックコンポーネントモデルを導入
第18回 JAX-RSで簡単RESTful - JSR 311
第17回 待望のServlet 3.0がJSRに登場 - JSR 315
第16回 アノテーションを使ってバグ退治 - JSR 305
第15回 アノテーションをさらに広い範囲で利用可能にするJSR 308
第14回 Webアプリケーション開発の要となるか - JSF 2.0がJSRに登場
第13回 Webサービス経由でのJMX Agentへの接続を可能にするJSR 262
第12回 Javaアプリケーションのモジュール化をサポートするJava Module System
第11回 "NIO.2"がやってきた - JSR 203: More New I/O APIs for the Java Platform
第10回 JSR 295: Beans Bindingの参照実装を試す
第9回 けっこう便利! 単位を扱うAPI -- JSR 275: Units Specification
第8回 アノテーションでバリデーション - JSR 303: Bean Validator
第7回 Swing開発の救世主となるか - Swing Application Framework
第6回 JavaBeansのプロパティを同期させるバインディングAPI
第5回 誰よりも早く"Java SE 7"を睨む
第4回 日時情報の取り扱いを改善する JSR 310: Date and Time API
第3回 古いAPIも進化している!? - JSR 919: JavaMail 1.4
第2回 JSR 1 リアルタイムJava仕様
第1回 JCPによって進められるJava関連技術の標準化

もっと見る



転職ノウハウ

あなたが本領発揮できる仕事を診断
あなたの仕事適性診断

シゴト性格・弱点が20の質問でサクッと分かる!

「仕事辞めたい……」その理由は?
「仕事辞めたい……」その理由は?

71%の人が仕事を辞めたいと思った経験あり。その理由と対処法は?

3年後の年収どうなる? 年収予報
3年後の年収どうなる? 年収予報

今の年収は適正? 3年後は? あなたの年収をデータに基づき予報します。

激務な職場を辞めたいが、美女が邪魔して辞められない
激務な職場を辞めたいが、美女が邪魔して辞められない

美人上司と可愛い過ぎる後輩に挟まれるエンジニアの悩み

人気記事

一覧

イチオシ記事

新着記事

求人情報