Primefaces selectManyCheckbox с редактируемой таблицей данных, отправляющей null в Converter

Я использую Primefaces selectManyCheckbox в редактируемой таблице данных подобной этой. Когда пользователь нажимает кнопку редактирования, он может выбирать между различными документами в столбце документов. Это мой код. Обратите внимание на конвертер, который я использую:

<p:dataTable id="tbl" styleClass="fixedLayoutTable no-highlight dblclick-edit edit-commit-others"
            value="#{cc.attrs.manager.mg}" var="mg"
             emptyMessage="#{msgs.noManager}" editable="true" widgetVar="tbl">
        <p:column  headerText="Documents">
            <p:cellEditor>
                <f:facet name="output">
                   <h:outputText value="#{msgs.noDocs}" rendered="#{mg.docs.size() == 0}" />
                <h:outputText value="#{mg.docs.toArray()[0].fileName}" rendered="#{mg.docs.size() > 0}" />
            </f:facet>
                <f:facet name="input">
                    <p:selectManyCheckbox id="chkDoc" 
                            value="#{mg.docs}" layout="pageDirection"
                            converter="myConverter" collectionType="java.util.HashSet">
                        <f:selectItems value="#{cc.attrs.manager.docs}"
                            var="d" itemValue="#{d}" itemLabel="#{d.fileName}" />
                    </p:selectManyCheckbox>
                </f:facet>
            </p:cellEditor>
        </p:column>
    </p:dataTable>

В другой вкладке приложения (давайте назовем ее Tab1) пользователь может загружать некоторые документы. Эти документы были добавлены в cc.attrs.manager.docs-список в компоненте поддержки, но еще не будут сохранены в базе данных. Если пользователь загружает некоторые документы в Tab1 и переходит на Tab2 (вкладку с данными), он должен иметь возможность выбирать между всеми документами, включая недавно добавленные. Таким образом, пользователь нажимает кнопку редактирования, и все документы появляются в поле SelectManyCheckbox. Если пользователь выбирает эти документы и щелкает, вызывается ✔-Подписать мой конвертер.

Я следовал этому примеру для реализации преобразователя. Вот фрагмент кода этого класса:

@FacesConverter(value="myConverter")
public class MyConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (component instanceof PickList) {
            return getAsObject((PickList)component, value);
        } else {
            return SelectItemsUtils.findValueByStringConversion(context, component, value, this);
        }
    }
}

Это работает нормально, пока пользователь не проверит недавно добавленные документы. Если он проверит один из новых документов, параметр String метода getAsObject-Method будет "нулевым". У кого-нибудь есть предложения, почему этот параметр равен нулю? Это потому, что документ еще не сохранен? Можно ли заставить это работать без сохранения документов, добавленных в Tab1?


person joshi737    schedule 22.12.2013    source источник


Ответы (2)


Вместо своего собственного converter попробуйте этот generic converter, который подойдет для всего.

import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.WeakHashMap;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

@FacesConverter(value = "entityConverter")
public class EntityConverter implements Converter {

    private static Map<Object, String> entities = new WeakHashMap<Object, String>();

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object entity) {
        synchronized (entities) {
            if (!entities.containsKey(entity)) {
                String uuid = UUID.randomUUID().toString();
                entities.put(entity, uuid);
                return uuid;
            } else {
                return entities.get(entity);
            }
        }
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String uuid) {
        for (Entry<Object, String> entry : entities.entrySet()) {
            if (entry.getValue().equals(uuid)) {
                return entry.getKey();
            }
        }
        return null;
    }

}
person Makky    schedule 23.12.2013
comment
Спасибо за ответ. Я попробовал ваш универсальный конвертер, но, к сожалению, строка uuid по-прежнему равна нулю... - person joshi737; 23.12.2013
comment
Тогда у вас есть проблемы с файлом XHTML. - person Makky; 23.12.2013
comment
Но почему-то он не равен нулю для тех документов, которые были в таблице до того, как были добавлены некоторые документы... - person joshi737; 23.12.2013
comment
@ joshi737 Я не могу понять твою проблему. Если бы вы могли опубликовать свой полный XHTML и управляемый компонент, я попробую проверить себя. - person Makky; 23.12.2013
comment
Извините, я не могу, потому что это довольно большое и сложное приложение... Что такое String-UUID? Каково это значение и как рассчитывается это значение? - person joshi737; 23.12.2013
comment
Теперь я понимаю. В моем случае это идентификатор сущности. Согласно моему вопросу, недавно загруженные документы не сохраняются, поэтому у них еще нет идентификатора. Что я могу сделать в этом случае? - person joshi737; 23.12.2013
comment
Как генерируется идентификатор? - person Makky; 23.12.2013
comment
давайте продолжим это обсуждение в чате - person Makky; 23.12.2013

Я решил это, реализовав другой преобразователь, который расширяет EntityConverter и проверяет, является ли идентификатор нулевым. Это мой код, например:

@FacesConverter(value = "anotherConverter")
public class AnotherConverter extends EntityConverter {

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value instanceof Document && ((Document) value).getId() == null) {
            return String.valueOf(((Document) value).hashCode());
        }
        return super.getAsString(context, component, value);
    }
}
person joshi737    schedule 27.12.2013