Struts2: aggiornamento dei valori di un “Elenco di oggetti” all’interno di una mappa

C’è un object ObjectA che ha una lista di ObjectB . C’è una TreeMap all’interno ObjectB . Questa TreeMap ha una String come chiave e una List di un altro object ObjectC come valore. Questa TreeMap e l’ list all’interno sono stati visualizzati su jsp usando s:iterator e s:textfield e viene visualizzato correttamente. cioè i “valori” all’interno del campo s: text sono corretti. Ora, il problema sorge quando il campo di testo viene modificato. Come catturiamo i valori modificati all’interno di ObjectC nella class action? Con il codice qui riportato, la chiave (“Key1”) viene visualizzata nell’azione ma il valore è null.

Codice Java

 public class ObjectA implements Serializable { private Integer attr1; private List objB; //...getters and setters.... public class ObjectB implements Serializable { private Integer attr11; private TreeMap<String,List> allPlainFields; // ...getters and setters.... public class ObjectC implements Serializable { private Integer attr111; public String attr112; // ...getters and setters.... 

Codice JSP

       

HTML reso:

La struttura dell’object nella vista “VAriables” di eclipse mostra :

     objA Object A (id=955) objB ArrayList (id=966) elementData Object[10] (id=967) [0] ObjectB (id=968) allPlainFields TreeMap (id=972) comparator null descendingMap null entrySet TreeMap$EntrySet (id=979) keySet null modCount 1 navigableKeySet null root TreeMap$Entry (id=980) size 1 values null [1] ObjectB (id=969) [2] ObjectB (id=970) [3] ObjectB (id=971) [4] null [5] null [6] null [7] null [8] null [9] null modCount 4 size 4 

    **** Nella vista “Variabili” di Eclipse, il valore di allPlainFields è **: ** {Key1 =}

    EDIT (27-Feb-2013) :

    Ho provato questo, ma non ha funzionato. I valori appaiono su jsp ma, quando vengono inviati, non entrano in azione:

    Nella class Action :

     private TreeMap testTreeMap = new TreeMap(); //get,set and setting two keys in map "mykey1" and "mykey2" 

    Nella class ObjectCList :

     private ArrayList paramMdlList; //default constructor, get, set 

    In JSP :

       
  • Save TreeMap

    Quando il modulo viene inviato, viene updateTreeMap metodo updateTreeMap action . La mappa è stampata come menzionato qui :

     public String updateTreeMap(){ for (Map.Entry entry : testTreeMap.entrySet()) { System.out.println(entry.getKey() + "/" + entry.getValue()); } return SUCCESS; 

    }

    Cosa è “stampato”: mykey1 / mykey2 / vale a dire valori nulli

    La schermata qui sotto mostra i valori che arrivano in jsp lo schermo che mostra i valori arriva in jsp

    Secondo il tuo ultimo aggiornamento. Se stai usando TreeMap Struts2 non puoi determinare correttamente il tipo di elementi al suo interno. Cambia dichiarazione di testTreeMap da TreeMap a Map .

     private Map testTreeMap = new TreeMap(); 

    Oppure annota testTreeMap con com.opensymphony.xwork2.util.Element annotazione com.opensymphony.xwork2.util.Element per dire a Struts2 che tipo sono gli elementi all’interno della mappa.

     @Element(value = ObjectCList.class) private TreeMap testTreeMap = new TreeMap(); 

    Sono diventato curioso e ho fatto altri esperimenti.

    Ho scoperto che né List s all’interno di List s, né Map s all’interno di Map s (e tutte le interpolazioni), dichiarato come interfaccia ( List , Map ), o come le loro implementazioni ( ArrayList , HashMap , TreeMap ) sono correttamente gestite da XWork Converter .

    Tutti i casi di test hanno fallito.

    Forse è colpa mia, se è così abbiamo davvero bisogno di alcuni esperti di OGNL , perché in tutto il web non c’è nulla di cui parlare.

    Poi ho provato quello che ero abbastanza sicuro che avrebbe funzionato: incapsulare queste informazioni in oggetti personalizzati , in puro modo OOP .

    E ha funzionato 🙂

    Invece di

     private ArrayList> outerObjects; 

    puoi usare nella tua azione

     private ArrayList outerObjects; /* GETTERS AND SETTERS */ public ArrayList getOuterObjects() { return outerObjects; } public void setOuterObjects(ArrayList outerObjects) { this.outerObjects = outerObjects; } 

    la definizione OuterObject :

     /* ELSEWHERE IN YOUR PROJECT... */ public class OuterObject{ private ArrayList innerObjects; /* GETTERS AND SETTERS */ public ArrayList getInnerObjects() { return innerObjects; } public void setInnerObjects(ArrayList innerObjects) { this.innerObjects = innerObjects; } } 

    la definizione InnerObject :

     public class InnerObject{ String innerField; /* GETTERS AND SETTERS */ public String getInnerField() { return innerField; } public void setInnerField(String innerField) { this.innerField = innerField; } } 

    il metodo opzionale execute () della tua azione per testare i valori preimpostati:

      InnerObject innerObj1 = new InnerObject(); innerObj1.setInnerField("Inner Value 1"); ArrayList innerObjArrayList = new ArrayList(); innerObjArrayList.add(innerObj1); OuterObject outerObj1 = new OuterObject(); outerObj1.setInnerObjects(innerObjArrayList); outerObjects = new ArrayList(); outerObjects.add(outerObj1); 

    il JSP :

          

    (durante l’iterazione, usa semplicemente [%{#stat.index}] per List s e ['%{#stat.index}'] per Map s)

    La stessa soluzione è applicabile per ogni tipo di struttura iterabile (probabilmente eccetto il materiale di Guava che richiede il metodo .create() per essere invocato).

    Naturalmente questo non è utile in ogni caso, nel tuo esempio hai già una struttura enorme e questo quasi raddoppierà , ma funziona, è OOP, il tuo OGNL sarà più chiaro (a causa dei nomi) e comunque sembra essere l’unico modo.

    Nota: le classi devono essere classi autonome reali, non Inner Classes , un altro caso in cui OGNL non riesce a rendere autowire gli oggetti.

    Spero possa aiutare


    MODIFICARE

    Quello di cui hai bisogno, quindi, è solo un altro livello:

    cambia questo:

     private TreeMap> allPlainFields; 

    a questa

     private TreeMap allPlainFields; 

    e creare un ObjectX contenente un campo privato che è un List .

    Funzionerà.