Сопоставление интерфейса с Moxy в binding.xml не работает с несколькими интерфейсами?

1

Я пытаюсь использовать Moxy v2.5.2 binding.xml для сопоставления класса в качестве альтернативы аннотациям, поскольку я не могу помещать аннотации в родительский класс третьей стороны.

EDIT: я изменил эту часть ниже после обратной связи с Blaise

Кажется, я не могу сопоставить интерфейс из-за родительских интерфейсов.

Фрагмент кода Java:

    public final class CmsContent {
        private ContentItemGroup group;
   .... getter/setters
 }

public class ContentItemGroupDefault extends CoreKeyBase implements ContentItemGroup {
    private String bla;
   .... getter/setters
}

Файл привязки:

<xml-bindings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" 
    package-name="com.core.domain" xml-mapping-metadata-complete="true" xml-accessor-type="NONE">

    <java-types>
        <java-type name="CmsContent" super-type="java.lang.Object" xml-accessor-type="NONE" >
            <xml-root-element name="content" />
            <java-attributes>
                <xml-element java-attribute="group" name="group" type="com.core.domain.impl.ContentItemGroupDefault" />
            </java-attributes>
        </java-type>

        <java-type name="ContentItemGroupDefault" super-type="java.lang.Object" xml-accessor-type="NONE">
            <java-attributes>
                <xml-attribute java-attribute="id" name="key"  /> <!-- from parent class -->
                <xml-transient java-attribute="name" />
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

И код для его маршала:

final Map<String, Object> properties = new HashMap<String, Object>();
final InputStream bindings = CmsContent.class.getResourceAsStream("jaxb-binding.xml");
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, bindings);
final Class<?>[] classes = new Class<?>[] { CmsContent.class};
final JAXBContext context = JAXBContext.newInstance(classes, properties);
final Marshaller marshaller = context.createMarshaller();

final CmsContent content = createCmsContent();
marshaller.marshal(content, System.out);

Известное исключение:

The java interface com.core.domain.ContentItemGroup can not be mapped by JAXB as it has multiple mappable parent interfaces. Multiple inheritence is not supported

Примечание: приведенный ниже пример @Blaise работает хорошо, спасибо за это, но этот пример не имеет нескольких родительских классов, как в моем случае, что вызывает исключение, даже в bind xml я использую атрибут super-type.

После отладки кода Moxy исключение возникает, когда класс Moxy "AnnotationsProcessor" проверяет все свойства CmsContent и пытается выяснить, является ли свойство ContentItemGroup в CmsContent Collection, метод: Helper.isCollectionType(..).

В методе Moxy JavaClassImpl.getSuperclass(..) он будет проходить через все родительские классы свойства интерфейса ContentItemGroup и будет терпеть неудачу, потому что родительский класс не запускается с "java" или "javax". Примечание. Интерфейс ContentItemGroup расширяет два интерфейса.

Почему он терпит неудачу и не использует ли он определенный супер-тип в привязке xml?

Он работает в случае, если ContentItemGroup не распространяется на какой-либо интерфейс или в случае, если он распространяется из одного интерфейса (который также учитывает все расширения родительских интерфейсов). В этом случае он успешно пройдет метод ниже. Однако удаление родительских интерфейсов не является вариантом :(

Другая проблема: BTW: когда она работает, как выводить свойства из родительского класса ContentItemGroupDefault в качестве атрибута xml? В приведенном выше примере "id" из родительского класса не отображается в xml. В случае, если я удаляю атрибут "супертипа", все свойства родительского класса появляются на выходе, даже когда я отмечаю их как "переходный". Что я делаю не так?

Метод JavaClassImpl.getSuperclass(..):

public JavaClass getSuperclass() {
    if(this.superClassOverride != null) {
        return this.superClassOverride;
    }
    if(jClass.isInterface()) {
        Class[] superInterfaces = jClass.getInterfaces();
        if(superInterfaces != null) {
            if(superInterfaces.length == 1) {
                return javaModelImpl.getClass(superInterfaces[0]);
            } else {
                Class parent = null;
                for(Class next:superInterfaces) {
                    if(!(next.getName().startsWith("java.") || next.getName().startsWith("javax."))) {
                        if(parent == null) {
                            parent = next;
                        } else {
                            throw JAXBException.invalidInterface(jClass.getName());
                        }
                    }
                }
                return javaModelImpl.getClass(parent);
            }
        }
    }
    return javaModelImpl.getClass(jClass.getSuperclass());
}

ОБНОВИТЬ:

@BLAISE:    <java-type name="AbstractCmsContent" xml-transient="true">

При изменении привязки xml ContentItemGroupDefault к (добавление xml-переходного процесса):

<java-type name="ContentItemGroupDefault" super-type="java.lang.Object" xml-accessor-type="NONE" xml-transient="true">

Я получаю следующее исключение:

Exception Description: A descriptor for class com.core.cms.moxy.ContentItemGroupDefault was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.

Который я не понимаю. Также при добавлении ContentItemGroupDefault в JAXContent эффект не имеет. При добавлении свойства "xml-transient" в сопоставление CmsContent, это приведет к тому же исключению, но затем приведет к классу CmsContent.

ОБНОВЛЕНИЕ: Тем временем я исправил его, используя Woodstox напрямую, что обошлось мне около 4 часов, включая тестирование. После дней разочарования я, похоже, не получаю Moxy для выполнения простого сопоставления. Даже если я ошибаюсь, я думаю, что Moxy может быть более дружественным/доступным для этих простых простых мета-отображений. При добавлении нескольких интерфейсов к интерфейсу PhoneNumber для @Blaise, приведенному ниже, я получаю ту же ошибку "Поддержка нескольких интерфейсов". Я хотел использовать Moxy, поскольку я использую его в других местах платформы, что касается тысяч сгенерированных классов jaxb, которые хорошо работают. Тем не менее, простой случай отображения кажется трудным.. :(

Теги:
jaxb
moxy

1 ответ

1

Когда у вас есть интерфейс с фронтальной моделью, это действительно классы реализации, которые вы сопоставляете. Ниже приведена ссылка на пример, который я демонстрирую, как это делается с аннотациями.

Для этого связанного примера ниже будет соответствующий документ сопоставления:

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="blog.interfaces">
    <java-types>
        <java-type name="CustomerImpl">
            <xml-root-element name="customer"/>
            <java-attributes>
                <xml-element java-attribute="address" type="blog.interfaces.AddressImpl"/>
                <xml-element java-attribute="phoneNumbers" name="phone-number" type="blog.interfaces.PhoneNumberImpl"/>
            </java-attributes>
        </java-type>
        <java-type name="PhoneNumberImpl">
            <java-attributes>
                <xml-value java-attribute="value"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

ОБНОВИТЬ

Спасибо @Blaise. С вашей обратной связью я снова изолировал проблему и обновил приведенный выше пример кода. Moxy не любит несколько родительских интерфейсов (ваш пример кода отлично работает, но не имеет нескольких интерфейсов)... Пожалуйста, обратная связь?

Проблема с несколькими родительскими интерфейсами должна возникать только в том случае, если вы пытаетесь обрабатывать интерфейс как отображаемую вещь. Моя рекомендация заключалась бы в том, чтобы не делать этого. Есть ли где-нибудь, что вы не переопределили свойство как фактический тип реализации?

Я не смог воспроизвести ошибку, которую вы видите. Следует отметить, однако, что когда вы делаете следующее, вы действительно говорите MOXy, что суперкласс этого класса - Object. Что касается MOXy, это не будет обрабатывать настоящий суперкласс CmsContent.

<java-type name="CmsContent" super-type="java.lang.Object" xml-accessor-type="NONE" >

Если вы просто хотите рассматривать суперкласс CmsContent как просто неотображаемый и иметь свойства, которые рассматриваются как свойства подклассов, тогда вы должны отметить этот класс как @XmlTransient. Это делается в метаданных XML, таких как:

<java-type name="AbstractCmsContent" xml-transient="true">
  • 0
    Спасибо, уже пробовал, но не работает, что приводит к проблеме (3) в моем описании выше, то есть определение "<java-type name =" impl.contentItemGroupDefault ">" приводит к "не удалось загрузить класс msgstr "ошибка moxy (имя пакета правильное). Как это решить? Также добавление класса реализации в контекст не имеет никакого эффекта :( Я знаю о вашем блоге (использовал его раньше, как и многие другие ваши сообщения;), спасибо за это.
  • 0
    Только что сделал небольшой тест: поместите все классы в один пакет (impl), и тогда я думаю, что он может найти класс ContentItemGroupDefault (пахнет как ошибка?), Но получаю другую ошибку, что ContentItemGroup (интерфейс) не может быть отображается как он имеет несколько интерфейсов. Это происходит, когда метод «AnnotationsProcessor.processPropertyAnnotations» обрабатывает свойства класса CmsContent. Странно, так как тип ContentItemGroup определен (см. Выше) так же, как вы делаете для phoneNumbers в вашем примере. Есть идеи?
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню