JSF Entityconverter ConcurrentModificationException - PullRequest
0 голосов
/ 11 мая 2018

Я использую общий конвертер сущностей в своем проекте.Я заметил, что иногда конвертер выдает java.util.ConcurrentModificationException Существует также 4 года Пост , на который нет ответа.

Я пытался использовать Iterator вместо простого for-loop но это не помогло.

Есть ли способ создать поточно-ориентированный конвертер?

@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) {

        Iterator<Map.Entry<Object, String>> tempIt = entities.entrySet().iterator();
        while (tempIt.hasNext()) {
            Map.Entry<Object, String> nextObj = tempIt.next();
            if (nextObj.getValue().equals(uuid)) {
                return nextObj.getKey();
            }
        }

        return null;
    }

}

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Другим способом достижения этого является использование Java ConcurrentMap , чтобы гарантировать безопасность потоков.В однострочнике:

private static ConcurrentMap<Object, String> entities = new ConcurrentHashMap<>();

@Override
public String getAsString(FacesContext context, UIComponent component, Object entity) {
    return entities.putIfAbsent(entity, UUID.randomUUID().toString());
}

Начиная с Java 8, вы также можете воспользоваться computeIfAbsent, который будет вычислять UUID только при отсутствии ключа:

return entities.putIfAbsent(entity, 
    entities.computeIfAbsent(k -> UUID.randomUUID().toString()));

Или даже улучшите его с помощью утилит кэширования Guava , если вы хотите сохранить слабые ссылки.

0 голосов
/ 11 мая 2018

Обернуть тело getAsObject в блок, синхронизированный на entities, как и в другом методе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...