JAXP — спорадические сбои теста XSLT

Код, прикрепленный ниже, вызывает спорадические сбои тестов (JUnit), работает в 80% случаев. Я использую статический объект Templates. В случае сбоя объект JAXB, отличный от ожидаемого, помещается в «результат» из вызова метода transform.transform(jaxbSource, result).

Пробовал блокировать и синхронизировать разделы тщетно. Также объект Templates должен быть потокобезопасным в соответствии со спецификацией. Что-то странное происходит в трансформации.

Симптом ошибки: сбой теста JUnit — внезапно из преобразования возвращается неправильный объект.

Есть идеи?

private <S, T> S transform(final Templates template, final Class resultClass, final T data) throws JAXBException, TransformerException {
    Transformer transformer = template.newTransformer();
    final JAXBSource jaxbSource = new JAXBSource(getCachedJAXBContext(data.getClass()), data);
    final Result result = new JAXBResult(getCachedJAXBContext(resultClass));
    transformer.transform(jaxbSource, result);
    return (S) ((JAXBResult) result).getResult();
}

person Theresia Sofia Snow    schedule 11.03.2011    source источник
comment
Понятия не имею, чем это вызвано. Было бы полезно пометить его как JAXB и более четко описать симптомы спорадических сбоев тестов, в идеале предоставив достаточно данных, чтобы другие могли воспроизвести проблему.   -  person Michael Kay    schedule 11.03.2011
comment
Да, это в значительной степени код с таблицами стилей XSL и тестовым кодом.   -  person Theresia Sofia Snow    schedule 11.03.2011
comment
Что делает getCachedJAXBContext()? Может ли это возвращать неправильный контент? Попробуйте записать/распечатать jaxbSource перед трансформацией, чтобы убедиться, что вы трансформируете то, что, по вашему мнению, вы из себя представляете.   -  person Mads Hansen    schedule 11.03.2011
comment
Он добавляет запись в ConcurrentHashMap, но ошибки присутствовали и до этого. contextMap.putIfAbsent (clazz, JAXBContext.newInstance (clazz));   -  person Theresia Sofia Snow    schedule 14.03.2011


Ответы (1)


Поскольку у вас есть несколько классов, сопоставленных с одним и тем же именем корневого элемента, вам необходимо передать тип, который вы хотите разархивировать, в качестве параметра операции демаршалирования. Это будет означать преобразование в промежуточное представление, такое как: DOM, byte[], String и т. д.:

private <S, T> S transform(final Templates template, final Class resultClass, final T data) throws JAXBException, TransformerException {
    Transformer transformer = template.newTransformer();
    final JAXBSource jaxbSource = new JAXBSource(getCachedJAXBContext(data.getClass()), data);
    final Result result = new DOMResult();
    transformer.transform(jaxbSource, result);
    return (S) getCachedJAXBContext(resultClass).createUnmarshaller().unmarshal(new DOMSource(result.getNode()), resultClass).getValue();
}

Чтобы получить больше информации:

person bdoughan    schedule 14.03.2011
comment
Да, я использовал эту конструкцию до кэширования JAXBContexts. Та же ошибка. - person Theresia Sofia Snow; 16.03.2011
comment
@Sigmund Lundgren. У вас есть несколько классов Java с одной и той же аннотацией @XmlRootElement? Это вызвало бы такое поведение. - person bdoughan; 16.03.2011
comment
Да, знаю.. Разные пакеты, но одно и то же имя. - person Theresia Sofia Snow; 16.03.2011
comment
Наличие общего имени @XmlRootElement вызывает проблему, я обновил свой ответ, указав способ обхода проблемы (при условии, что у вас не может быть уникальных корневых элементов). - person bdoughan; 16.03.2011
comment
Это служба маршрутизации, фактически только новое пространство имен, поэтому мы попробуем переименовать одно из них. Спасибо! - person Theresia Sofia Snow; 16.03.2011