Chúng tôi đã sử dụng JAXB 2.1 trong một thời gian dài trong hệ thống của chúng tôi. Chúng tôi có một nền tảng được xây dựng với Ant và tạo ra một loạt các gói được triển khai trong thời gian chạy OSGi. Chúng tôi sử dụng Java SE 6.Hai lớp có cùng tên kiểu XML "objectFactory"
Chúng tôi sử dụng JAXB trong quá trình xây dựng để tạo ra kiểu dữ liệu từ các lược đồ khác nhau. Các lớp đó được đóng gói trong các gói và được sử dụng trong thời gian chạy để tuần tự hóa/deserialize nội dung. Ngoài ra, chúng tôi sử dụng JAXB trong nền tảng của chúng tôi trong thời gian chạy để tạo các kiểu dữ liệu từ các lược đồ khác do người dùng cung cấp (nó là một loại nền tảng MDA).
Trong thời gian chạy OSGi, chúng tôi có một gói có các lọ JAXB và xuất các gói cần thiết. Chúng ta tạo một cá thể JAXBContext với đường dẫn ngữ cảnh của tất cả các nhà máy đối tượng được tạo ra, vì vậy chúng ta có thể marshall/unmarshall tất cả các kiểu dữ liệu của chúng ta.
Điều đó đã hoạt động cho đến nay nhưng hiện tại chúng tôi đang cố gắng nâng cấp lên phiên bản ổn định mới nhất của JAXB (2.2.4) và chúng tôi đang gặp sự cố khi cố gắng tạo ngữ cảnh trong thời gian chạy. Chúng tôi nhận được ngoại lệ sau đây:
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
Các lỗi Hai lớp học có cùng tên kiểu XML "objectFactory" được in ra cho mỗi người trong số các nhà máy đối tượng được tạo ra trong quá trình xây dựng.
Chúng tôi đã thấy một số bài đăng trong SO có cùng lỗi nhưng áp dụng cho các loại được tạo, không áp dụng cho nhà máy đối tượng. Chúng tôi nghĩ rằng JAXB có thể không xác định được lớp ObjectFactory như một nhà máy đối tượng mà là một kiểu dữ liệu.
Một khả năng là chúng tôi đã sử dụng phiên bản nội bộ của JAXB trong Java 6, vì vậy chúng tôi quyết định sử dụng tài sản Hệ thống -Djava.endorsed.dirs và đưa ba lọ (jaxb-api-2.2.4 .jar, jaxb-impl-2.2.4.jar và jaxb-xjc-2.2.4.jar) trong đường dẫn đó, nhưng vẫn không hoạt động.
Chúng tôi nghĩ rằng vấn đề có thể là chúng tôi đang sử dụng một phiên bản JAXB khác trong thời gian chạy OSGi và trong quá trình xây dựng, do đó mã được tạo không tương thích. Nhưng có lẽ chúng ta sai và có một vấn đề khác.
Bạn có ý tưởng nào không?
Xin cảm ơn trước.
(Edit: thêm chi tiết về vấn đề này)
Chúng tôi tạo ra các JAXBContext theo cách này:
ClassLoader classLoader = new JAXBServiceClassLoader(getParentClassLoader(),
Collections.unmodifiableMap(objectFactories));
context = JAXBContext.newInstance(contextPath.toString(), classLoader);
nơi contextPath là một chuỗi có chứa tất cả các nhà máy đối tượng của chúng tôi cách nhau bởi ':', và JAXBServiceClassLoader là:
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;
}
}
(chỉnh sửa: sau khi đăng bài của Aaron)
Tôi đã gỡ lỗi tất cả nội bộ của JAXBContextImpl và điều này là JAXBContextImpl đang cố gắng lấy thông tin kiểu từ lớp ObjectFactory của chúng tôi, điều này là sai. Trong thực tế, trong com.sun.xml.internal.bind.v2.model.impl.ModelBuilder: 314, hàm getClassAnnotation() trả về null nhưng khi tôi nhìn thấy cá thể tôi có thể thấy chú thích XmlRegistry.
Vấn đề là tại thời điểm đó XmlRegistry.class.getClassLoader() trả về null, nhưng nếu tôi chạy ((Class) c) .getAnnotations() [0] .annotationType(). GetClassLoader() nó trả về classLoader của gói OSGi "lib.jaxb" có chứa các JAXB jars của tôi, đó là chính xác.
Vì vậy, tôi đoán rằng chúng tôi đang tải cùng một lúc hai phiên bản khác nhau của XmlRegistry, một từ JDK và một phiên bản khác từ JAXB 2.2.4 lọ. Câu hỏi đặt ra là: tại sao?
Và thậm chí nhiều hơn, thay vì tải tất cả các lớp com.sun.xml.internal. * (Như JAXBContextImpl), không được tải và thực thi com.sun.xml.bind.v2.runtime.JAXBContextImpl từ JAXB lọ? Trong quá trình gỡ lỗi, tôi có thể thấy rằng nó đang làm một số công cụ với sự phản ánh nhưng tôi không hiểu tại sao làm điều đó.
Sử dụng Java SE 6 Tôi khuyên bạn nên sử dụng bản vá lỗi mới nhất của JAXB impl hỗ trợ JAXB 2.1 trừ khi có một tính năng JAXB 2.2 cụ thể mà bạn đang cố gắng sử dụng. –
Xin lỗi vì tôi không đề cập đến điều đó. Lý do để nâng cấp lên JAXB 2.2.4 là chúng tôi đang nâng cấp phiên bản JAX-WS lên 2.2.5 và nó phụ thuộc vào phiên bản JAXB đó (http://jax-ws.java.net/2.2.5/docs/ ReleaseNotes.html). Nếu không, chúng ta có thể sử dụng JAXB 2.1. – Denian
Dường như JAXB của bạn đang xử lý nhầm lẫn 'ObjectFactory' như một lớp miền. Điều này rất có thể là do chú thích '@ XmlRegistry' không được nhận ra do sự khác biệt' ClassLoader' giữa các lớp miền của bạn và việc triển khai JAX-WS. Bạn có đang tạo trực tiếp 'JAXBContext' hoặc thực hiện JAX-WS làm việc này không? –