DWRのオブジェクト変換

DWRのオブジェクト変換ではできないこと

DWRでは、JavaScript連想配列を作って、リモートオブジェクトの引数にすることができます。それについては公式ドキュメントのイントロダクションを見てください*1


ただし、次の場合オブジェクトを変換することはできません。

  • リモートオブジェクトで定義してるメソッドの引数と、JavaScriptから連想配列で作って渡すオブジェクトのプロパティが異なる場合
    • この場合JavaScriptで引数として渡すオブジェクトは、定義されている引数とインタフェイスが同じであったり、サブクラスであってもだめです。
こんな例を考える
名前 タイプ 詳細
StringBean クラス ContentsBeanを実装したデータ型
ContentsBean インタフェイス データ型
ContentsBeanContener クラス ContentsBeanを保持するためのデータ型


これをhtmlから呼んでみます

function post(){
    var stringBean = {str:"値を送信してみます"};
    StringBeanContener.setBean(stringBean);
}

StringBeanクラスを意識して作った連想配列をsetBeanに渡します。


ContentsBeanContenerには次のようなメソッドを実装する

public void setBean(ContentsBean bean){
  this.bean = bean;
}
public ContentsBean getBean(){
  return this.bean;
}

実際にsetBeanが受け取る引数はStringBeanでなく、ContentsBeanです。


StringBean

public class StringBean implements ContentsBean{
  String str;

  //コンストラクタ
  public StringBean(String str){ this.str = str }

  getterとsetter…

}

その代わりStringBeanはContentsBeanを実装して作られています.


ContentsBeanインタフェイス

interface ContentsBean{
}

これは特に中身を決めていません


これを実行するとサーバのコンソールにこんなエラーが表示されます

No methods called class 'ContentsBeanContener.setBean' are applicable for the passed parameters.

どうやらsetBeanの引数はStringBeanとして定義しないといけなかったようです。

この場合こう直すのが正解

ContentsBeanContenerには次のようなメソッドを実装する

public void setBean(StringBean bean){
  this.bean = bean;
}
public StringBean getBean(){
  return this.bean;
}

引数の型と返り値の型を変更しました。

逆にサーバから値を受け取る場合はインタフェイスを使っても大丈夫です

ContentsBeanContenerのgetBeanメソッドをindex.htmlから実行してみます。これを実行するとContentsBean(実体はStringBean)が返ってきます。この場合はContentsBeanをStringBeanと同じように扱えます

function call(){
    ContentsBeanContener.getBean(callback);
}
function callback(bean){
    document.write(bean.str);   //インタフェイスはContentsBeanだが、StringBeanが入ってる
}