Два класса имеют одно и то же имя типа XML «objectFactory»

Мы давно используем JAXB 2.1 в нашей системе. У нас есть платформа, созданная с помощью Ant и генерирующая набор пакетов, которые развертываются в среде выполнения OSGi. Мы используем Java SE 6.

Мы используем JAXB в процессе сборки для генерации типов данных из разных схем. Эти классы упакованы в пакеты и используются во время выполнения для сериализации / десериализации контента. Кроме того, мы используем JAXB на нашей платформе во время выполнения для генерации типов данных из других схем, предоставленных пользователем (это своего рода платформа MDA).

В среде выполнения OSGi у нас есть пакет, который содержит jar-файлы JAXB и экспортирует необходимые пакеты. Мы создаем экземпляр JAXBContext с контекстным путем всех сгенерированных фабрик объектов, чтобы мы могли маршалировать / демаршалировать все наши типы данных.

Пока это работает, но сейчас мы пытаемся обновить до последней стабильной версии JAXB (2.2.4) , и у нас возникают проблемы при попытке создать контекст во время выполнения. Мы получаем следующее исключение:

Two classes have the same XML type name "objectFactory". Use @XmlType.name and @XmlType.namespace to assign different names to them.
    this problem is related to the following location:
        at some.package.ObjectFactory
    this problem is related to the following location:
        at some.other.package.ObjectFactory

    at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:436)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1100)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:143)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:110)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:191)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:187)
    ... 76 more

Ошибка Два класса имеют одинаковое имя типа XML. «ObjectFactory» печатается для каждой из фабрик объектов, созданных в процессе сборки.

Мы видели несколько сообщений в SO с той же ошибкой, но применительно к сгенерированным типам, а не к фабрике объектов.Мы думаем, что JAXB может идентифицировать класс ObjectFactory не как фабрику объектов, а как тип данных.

Одна из возможностей заключалась в том, что мы использовали внутреннюю версию JAXB в Java 6, поэтому мы решили использовать свойство системы -Djava.endorsed.dirs и поместить три jar-файла ( jaxb- api-2.2.4.jar, jaxb-impl-2.2.4.jar и jaxb-xjc-2.2.4.jar ) по этому пути, но по-прежнему не работает.

Мы думаем, что проблема может заключаться в том, что мы используем другую версию JAXB в среде выполнения OSGi и в процессе сборки, поэтому сгенерированный код несовместим. Но, возможно, мы ошибаемся и возникает другая проблема.

У вас есть идеи?

Заранее спасибо.

(Edit: подробнее об этом)

Мы создаем JAXBContext следующим образом:

    ClassLoader classLoader = new JAXBServiceClassLoader(getParentClassLoader(),
                                                         Collections.unmodifiableMap(objectFactories));
    context = JAXBContext.newInstance(contextPath.toString(), classLoader);

где contextPath - это строка, содержащая все наши фабрики объектов, разделенные ':', а JAXBServiceClassLoader:

  private static final class JAXBServiceClassLoader extends ClassLoader
  {
    @NotNull
    private final Map<String, Object> objectFactories;

    private JAXBServiceClassLoader(@NotNull ClassLoader parent, @NotNull Map<String, Object> objectFactories)
    {
      super(parent);
      this.objectFactories = objectFactories;
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException
    {
      Class<?> ret;
      try
      {
        ret = super.loadClass(name);
      }
      catch (ClassNotFoundException e)
      {
        Object objectFactory = objectFactories.get(name);
        if (objectFactory != null)
        {
          ret = objectFactory.getClass();
        }
        else
        {
          throw new ClassNotFoundException(name + " class not found");
        }
      }
      return ret;
    }
  }

(Правка: после сообщения Аарона)

Я отлаживал все внутренние компоненты JAXBContextImpl, и дело в том, что JAXBContextImpl пытается получить информацию о типе из наших классов ObjectFactory, что неверно. Фактически, в com.sun.xml.internal.bind.v2.model.impl.ModelBuilder: 314 вызов getClassAnnotation () возвращает значение null, но когда я вижу экземпляр, я вижу аннотацию XmlRegistry.

Дело в том, что в этот момент XmlRegistry.class.getClassLoader () возвращает null, но если я запускаю ((Class) c) .getAnnotations () [0] .annotationType (). GetClassLoader (), он возвращает classLoader пакета OSGi "lib.jaxb", который содержит мои jar-файлы JAXB, и это правильно.

Итак, я предполагаю, что мы загружаем одновременно две разные версии XmlRegistry, одну из JDK, а другую из jar-файлов JAXB 2.2.4. Возникает вопрос: почему?

И даже более того, вместо загрузки всех этих классов com.sun.xml.internal. * (Например, JAXBContextImpl) не следует загружать и выполнять com.sun.xml.bind.v2 .runtime.JAXBContextImpl из jar-файлов JAXB? Во время процесса отладки я вижу, что он что-то делает с отражением, но я не понимаю, почему это происходит.

7
задан Denian 14 September 2011 в 17:01
поделиться