2012-09-09 5 views
7

Ich bin mir nicht sicher, ob dies ein komplexes Problem ist, aber als Startperson scheint mir das etwas komplex zu sein. Ich habe ein Objekt, basierend auf dem ich einige Werte auf der Benutzeroberfläche anzeigen und Benutzer einige auswählen müssen, muss ich Daten an einen anderen Controller zurücksenden, wenn Benutzer auf die Schaltfläche Senden klicken. Hier ist die Struktur meines DatenobjektsBindung einer Liste von Listen im Frühjahr MVC

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

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

public ConfiguredDesignData{ 
    // simple fields 
} 

ich habe das Objekt im Modell festgelegt, bevor die Ansicht wie

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

in Form zeigt, ich habe folgende Einstellungen

<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> 

Das ist, was ich

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) 

Auf Absenden des Formulars Ausnahme

folgende ich bin immer bei AddProductToCartController haben
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 

Es scheint, wie seine Werte auf diesem Controller zuzugreifen versuchen, während ich versuche, Wert zu senden zu diesem Controller und versuchen, gleiches Objekt mit ausgewählten Werten

Kann jemand mir sagen, zu schaffen, wo ich falsch mache und was ich brauche von

kümmern

bearbeiten

Ich habe einige mehr Forschung und kam zu wissen, dass Frühling nicht unterstützen Autofüllfunktion Liste/Karte für benutzerdefinierte Objekte und auf der Grundlage der Antwort, die ich versuchte Implementierung zu ändern wie

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)); 

    } 
    } 

aber ich bin immer folgende Ausnahme

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 [[email protected]] 

ich bin nicht sicher was, was ich falsch mache, scheint es, dass entweder mein JSTL Ausdruck ist nicht richtig

+0

Eine andere Sache zu achten gilt in diesem Szenario verschachtelte Klassen ist. Wenn Sie 'PrsCDData' zu einer Top-Level-Klasse machen, können Sie dieses Problem vermeiden. –

Antwort

7

Erläuterung: Wenn Sie in Ihrem Controller @ModelAttribute("user") User user haben und eine entsprechende Seite laden, die <form:form commandName="user"> enthält, wird ein leerer Benutzer instanziiert.

Alle seine Attribute sind Null oder leer im Falle einer Liste oder einer Karte. Darüber hinaus wurden seine leeren Listen/Maps mit einer Autogrowing-Implementierung instanziiert. Was heißt das ? Nehmen wir an, wir haben eine leere Autogrowing List<Coconut> coconuts. Wenn ich coconuts.get(someIndex).setDiameter(50) mache, wird es funktionieren, anstatt eine Ausnahme zu werfen, weil die Liste automatisch wächst und eine Kokosnuss für den gegebenen Index instanziiert.
Dank diesen autogrowing, ein Formular mit der folgenden Eingabe einreichen wird wie ein Zauber funktionieren:

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

, um Ihr Problem nun zurück: Spring MVC autogrowing recht gut mit einer Kette von Objekten arbeitet, Jede enthält eine Karte/Liste (see this post). Aber aufgrund Ihrer Ausnahme sieht es so aus, als würde Spring die möglichen Objekte, die in der automatisch gegangenen Liste/Karte enthalten sind, nicht automatisch vergrößern.In Map<String, List<PrsCDData>> prsCDData ist die List<PrsCDData> eine bloße leere Liste ohne Autogrowing, was zu Ihrer Exception führt.

Also die Lösung muss eine Art von Apache Common LazyList oder Spring AutoPopulatingList verwenden.
Sie müssen Ihre eigene Autograving-Map implementieren, die eine LazyList/AutoPopulatingList für einen bestimmten Index instanziiert. Tun Sie es von Grund auf neu oder verwenden Sie eine Art von Apache Common LazyMap/MapUtils.lazyMap Implementierung (bisher habe ich kein Spring-Äquivalent für LazyMap gefunden).

Beispiel Lösung unter Verwendung von Apache Commons Kollektionen:

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)); 
      } 

     }); 
    } 

} 
+0

Schöne Erklärung! Wird nach Ihrem Vorschlag versuchen und wird –

+0

versuchen ersten Ansatz geben folgenden Ausnahme 'org.springframework.beans.NullValueInNestedPathException: Ungültige Eigenschaft' prsBTOData 'der Bean-Klasse [com.data.PrsData]: Konnte nicht instanziieren Eigenschaftstyp [Org .springframework.util.AutoPopulatingList] zum automatischen Erweitern des geschachtelten Eigenschaftspfads: java.lang.IllegalArgumentException: Konnte nicht instanziiert Sammlungsart: org.springframework.util.AutoPopulatingList' –

+0

Kannst du den zweiten Ansatz mehr erklären als es nicht sehr klar ist mich. –