7

これが複雑な問題かどうかはわかりませんが、初心者としては少し複雑に思えます。UIにいくつかの値を表示し、ユーザーがそれらのいくつかを選択できるようにする必要があるオブジェクトがあり、ユーザーが送信ボタンをクリックしたときにデータを別のコントローラーに送り返す必要があります。データオブジェクトの構造は次のとおりです

public class PrsData{
private Map<String, List<PrsCDData>> prsCDData;
}

public class PrsCDData{
  private Map<String, Collection<ConfiguredDesignData>> configuredDesignData;
}

public ConfiguredDesignData{
  // simple fields
}

ビューを次のように表示する前に、モデルにオブジェクトを設定しました

model.addAttribute("prsData", productData.getPrData());

フォームには次の設定があります

<form:form method="post" commandName="prsData" action="${addProductToCartAction}" >
<form:hidden path="prsCDData['${prsCDDataMap.key}']
  [${status.index}].configuredDesignData['${configuredDesignDataMap.key}']
  [${configuredDesignDataStatus.index}].code"/>

<form:hidden path="prsCDData['${prsCDDataMap.key}']
  [${status.index}].configuredDesignData['${configuredDesignDataMap.key}']
  [${configuredDesignDataStatus.index}].description"/>

</form:form>

これは私が持っているものですAddProductToCartController

public String addToCart(@RequestParam("productCodePost") final String code,
@ModelAttribute("prsData") final PrsData prsData, final Model model,
@RequestParam(value = "qty", required = false, defaultValue = "1") final long qty)

フォームを送信すると、次の例外が発生します

org.springframework.beans.NullValueInNestedPathException: Invalid property 'prsCDData[Forced][0]' 
of bean class [com.product.data.PrsData]: 
Cannot access indexed value of property referenced in indexed property path 'prsCDData[Forced][0]': returned null

そのコントローラーに値を送信しようとしていて、選択した値で同じオブジェクトを作成しようとしているときに、このコントローラーの値にアクセスしようとしているようです

どこが間違っているのか、何を世話する必要があるのか​​ 教えてもらえますか

編集

さらに調査を行ったところ、Spring はカスタム オブジェクトのリスト/マップの自動入力をサポートしていないことがわかりました。その答えに基づいて、実装を次のように変更しようとしました。

public class PrsData{
    private Map<String, List<PrsCDData>> prsCDData;
    // lazy init
    public PrsData()
    {
           this.prsCDData = MapUtils.lazyMap(new HashMap<String, List<PrsCDData>>(),
                FactoryUtils.instantiateFactory(PrsCDData.class));
        }
    }

    public class PrsCDData{
      private Map<String, Collection<ConfiguredDesignData>> configuredDesignData;
      public PrsCDData()
    {

       this.configuredDesignData = MapUtils.lazyMap(new HashMap<String,  
                                      List<ConfiguredDesignData>>(),
            FactoryUtils.instantiateFactory(ConfiguredDesignData.class));

    }
    }

しかし、次の例外が発生しています

org.springframework.beans.InvalidPropertyException: 
Invalid property 'prsCDData[Forced][0]' of bean class [com.data.PrsData]:
Property referenced in indexed property path 'prsCDData[Forced][0]' 
is neither an array nor a List nor a Set nor a Map; 
returned value was [com.data.PrsCDData@6043a24d]

どちらが間違っているのかわかりません.JSTL表現が正しくないようです.

4

1 に答える 1

9

説明 :コントローラーに があり@ModelAttribute("user") User user、 を含む対応するページをロードすると<form:form commandName="user">、空のユーザーがインスタンス化されます。

List または Map の場合は、すべての属性が null または空です。さらに、その空のリスト/マップは、自動拡張の実装でインスタンス化されています。どういう意味ですか ?空の autogrowing があるとしましょうList<Coconut> coconuts。リストが自動的に成長しcoconuts.get(someIndex).setDiameter(50)、指定されたインデックスのココナッツをインスタンス化するため、例外をスローする代わりに機能します。
この自動拡張のおかげで、以下の入力を含むフォームを送信すると、魅力的に機能します。

<form:input path="coconuts[${someIndex}].diameter" />

ここで問題に戻ります。Spring MVC の自動拡張は、それぞれがマップ/リストを含むオブジェクトのチェーンで非常にうまく機能します (この投稿を参照)。しかし、あなたの例外を考えると、Spring は自動拡張されたリスト/マップに含まれる可能性のあるオブジェクトを自動拡張しないようです。ではMap<String, List<PrsCDData>> prsCDDataList<PrsCDData>自動拡張のない単なる空のリストであるため、例外が発生します。

したがって、ソリューションでは、ある種の Apache Common のLazyListまたは Spring のAutoPopulatingListを使用する必要があります。
特定のインデックスの LazyList/AutoPopulatingList をインスタンス化する独自の自動拡張マップを実装する必要があります。ゼロから行うか、ある種の Apache Common のLazyMap / MapUtils.lazyMap実装を使用します (これまでのところ、LazyMap に相当する Spring は見つかりませんでした)。

Apache Commons Collections を使用したソリューションの例:

public class PrsData {

  private Map<String, List<PrsCDData>> prsCDData;

  public PrsData() {
      this.prsCDData = MapUtils.lazyMap(new HashMap<String,List<Object>>(), new Factory() {

          public Object create() {
              return LazyList.decorate(new ArrayList<PrsCDData>(), 
                             FactoryUtils.instantiateFactory(PrsCDData.class));
          }

      });
  }

}
于 2012-09-09T15:35:49.067 に答える