struts 2: захват изменений в таблице guava (TreeBasedTable) в действии

Существует объект (ObjectA), внутри которого находится другой объект (ObjectB). Внутри объекта B есть Guava TreeBasedTable. Эта таблица имеет строку как ключ строки, ключ столбца и другой объект «ObjectC» в качестве значения. Эта таблица отображается на jsp с использованием тегов <s:iterator/> и <s:textfield/> и отображается правильно ("значения" внутри <s:textfield/> верны, а "имена" - нет).

Теперь проблема возникает при изменении <s:textfield/>. Как мы фиксируем измененные значения внутри ObjectC в классе действия?

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

JSP-код:

<!-- language: lang-html -->

<s:iterator value="#objB.allPlainFields.row(#rowKey)" var="fieldMap"
    status="fieldStatus">
    <li><label><s:property value="#fieldMap.key" /></label><span>
            <s:textfield name="<NOT SURE>" value="%{#fieldMap.value.attr12}" />
    </span></li>
</s:iterator>

TreeBasedTable в Guava похоже на карту внутри карты, я пытался сделать allPFields[#outerkey][#innerkey].attr112, но это не сработало.

Структура объекта при отображении экрана с существующими значениями в базе данных

<!-- language: lang-java -->
objA        
objBList    ArrayList<E>  (id=668)  
elementData Object[10]  (id=7438)   
    [0] objB  (id=7439) 
        allPFields  TreeBasedTable<R,C,V>  (id=7443)    
            backingMap  TreeMap<K,V>  (id=8116) 
            cellSet null    
            columnComparator    NaturalOrdering  (id=503)   
            columnKeySet    null    
            columnMap   null    
            factory TreeBasedTable$Factory<C,V>  (id=8117)  
            rowKeySet   null    
            rowKeySet   StandardRowSortedTable$RowKeySortedSet  (id=8118)   
            rowMap  StandardRowSortedTable$RowSortedMap  (id=8119)  
            rowMap  null    
            values  null

А «allPFields» в действии выглядит следующим образом:

{OuterKey1=
    {InnerKey1=ObjectC[attr111=31, attr112=Hi there], 
     InnerKey2=ObjectC[attr111=40, attr112=How are you]
    }
 }

Приведенное выше значение allPFields было взято из консоли IDE.


person Vickym    schedule 20.02.2013    source источник


Ответы (1)


Как я уже говорил вам в другом вопросе, я никогда не использовал Guava TreeBasedTable;

Однако, согласно официальной документации по Guava,

TreeBasedTable , который is essentially backed by a TreeMap<R, TreeMap<C, V>>

и get метод

V get(Object rowKey, Object columnKey)

Возвращает значение, соответствующее заданным ключам строки и столбца, или null, если такое сопоставление не существует.

В Java это будет:

Object value = objA.getObjB().get(listIndex).getAllPlainFields.get(rowKey, columnKey).getAttr112;
value = "new value";

Затем в OGNL вы можете попробовать что-то (совершенно непроверенное), например:

<s:textfield value="%{#fieldMap.value.attr12}"
 name="objA.objB[#fieldStatus.index].allPlainFields.get(#rowKey, #fieldMap.Key).attr112"  />

P.S: ОСТЕРЕГАЙТЕСЬ ОПЕЧАТКИ... вы используете allPlainFields и allPFields вместе... одно из них неверно, убедитесь, что все обозначения указывают на правильное имя переменной.

P.P.S: Я не знаю ваших требований, но эта структура кажется мне немного переработанной... она определенно не соответствует KISS paradigm :)

person Andrea Ligios    schedule 20.02.2013
comment
Пробовал, но не сработало: ` ‹s:textfield name=objA.objB[%{#fieldStatus.index}].allPlainFields.get('%{#rowKey}','%{#fieldMap.key}') .attr112 value=%{#fieldMap.value.attr112} /›` ....почему-то мне не удалось заставить методы работать с использованием OGNL. В тот момент, когда я использую метод, объект (ObjB) отправляется как null. - person Vickym; 20.02.2013
comment
Ааа... вы отключили Dynamic Method Invocation в Struts.xml (если да, включите его снова)? Вы проверили, является ли геттер в ObjectB getAllPFields или getAllPlainFields ? - person Andrea Ligios; 20.02.2013
comment
Да, для Dynamic Method Invocation установлено значение false.. Я включил его... сейчас проверю. - person Vickym; 20.02.2013
comment
Тем не менее objB имеет значение null в действии ... <s:textfield> отображается как <input type="text" id="review-act_objA_objB_0__allPlainFields_get('rowKey1',' column_key1')_attr112" value="correct value" name="objA.objB[0].allPlainFields.get('rowKey1',' column_key1').attr112"> .... Пробовал и с row(rowkey)[columnkey]. - person Vickym; 20.02.2013
comment
Следующий код приводит в действие ненулевой objB, но allPlainfields по-прежнему NULL. Код: objA.objB[%{#fieldStatus.index}].allPlainFields['%{rowKey}']['%{#fieldMap.key}'].attr112..... есть еще подсказки? Я понял про ваше утверждение о сложности... Нам нужно вывести на экран таблицу (Карта,Карта) и отсюда выбор.... - person Vickym; 20.02.2013
comment
это все PlainFields. жаль пропустил. - person Vickym; 20.02.2013
comment
еще одна интересная вещь. Если я определяю textfield следующим образом, значение отображается правильно. Это означает, что атрибут value принимает метод, а name — нет. <s:textfield name="tempVal" value="%{objA.objB[0].allPlainFields.row('OuterKey1')['InnerKey1'].attr112}" /> - person Vickym; 20.02.2013
comment
продвигаемся вперед: следующий код в итераторе отображает правильное значение, но когда значение изменено и отправлено, objB в action по-прежнему имеет значение null. Обратите внимание, что атрибут value не упоминается для textfield. Это означает, что атрибута name достаточно для отображения value. <s:textfield name="objA.objB[%{#fieldStatus.index}].allPlainFields.row('%{rowKey}')['%{#fieldMap.key}'].attr112" /> - person Vickym; 20.02.2013
comment
У вас есть конструкторы по умолчанию (без аргументов) в ваших объектах? Я имею в виду явное определение ИЛИ отсутствие других определений конструкторов? Возможно, что-то мешает корректному созданию экземпляра объекта OGNL... - person Andrea Ligios; 20.02.2013
comment
ObjectA, ObjectB и ObjectC имеют no args constructor. Однако TreeBasedTable должен быть создан с использованием TreeBasedTable.create(). Может ли это быть проблемой? - person Vickym; 20.02.2013
comment
Абсолютно да. Но я провожу некоторые эксперименты с использованием TreeMap<String, TreeMap<String,String>>, и это не работает так же. Боюсь, проблема в двойном кастинге... следите за обновлениями. - person Andrea Ligios; 20.02.2013
comment
В настоящее время рассматриваются проблемы в apache jira: [ссылка]issues.apache.org/jira/browse /WW-3866 [ссылка]issues.apache.org/jira/browse /ОГНЛ-221 - person Vickym; 20.02.2013
comment
Хорошо... Я сейчас использую эту версию (2.3.1.2), затронутую проблемой, и попробовал с TreeMap, как в Jira. Попробуйте обновить S2 (в целях тестирования) и использовать вложенную древовидную карту вместо материала Guava, что добавляет проблему метода .create()... дайте нам знать - person Andrea Ligios; 20.02.2013
comment
Пробовал с TreeMap‹String, List‹ObjectC››, но столкнулся с проблемой. [stackoverflow.com/q/15006868/2087216] - person Vickym; 21.02.2013