2011-09-09 9 views
5

हम अपने सिस्टम में लंबे समय तक जेएक्सबी 2.1 का उपयोग कर रहे हैं। हमारे पास एक मंच है जो चींटी के साथ बनाया गया है और ओएसजीआई रनटाइम में तैनात बंडलों का एक गुच्छा उत्पन्न करता है। हम जावा एसई 6.दो वर्गों में एक ही एक्सएमएल प्रकार का नाम "ऑब्जेक्ट फैक्ट्री"

का उपयोग करते हैं हम विभिन्न योजनाओं से डेटाटाइप उत्पन्न करने के लिए निर्माण प्रक्रिया के दौरान जेएक्सबी का उपयोग करते हैं। उन वर्गों को बंडलों में पैक किया जाता है और सामग्री को क्रमबद्ध/deserialize करने के लिए रनटाइम में उपयोग किया जाता है। इसके अलावा हम उपयोगकर्ता द्वारा प्रदान किए गए अन्य स्कीमा से डेटाटाइप उत्पन्न करने के लिए रनटाइम में हमारे प्लेटफॉर्म में जेएक्सबी का उपयोग करते हैं (यह एक प्रकार का एमडीए मंच है)।

ओएसजीआई रनटाइम में हमारे पास एक बंडल है जिसमें जेएक्सबी जार हैं और आवश्यक पैकेज निर्यात करते हैं। हम उत्पन्न सभी ऑब्जेक्ट कारखानों के संदर्भ पथ के साथ एक 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 

त्रुटि दो कक्षाएं एक ही एक्सएमएल प्रकार का नाम "objectFactory" है निर्माण प्रक्रिया के दौरान उत्पन्न वस्तु कारखानों से प्रत्येक के लिए मुद्रित है।

हमने एसओ में एक ही त्रुटि के साथ कई पोस्ट देखी हैं लेकिन उत्पन्न कारखाने के लिए जेनरेट किए गए प्रकारों पर लागू नहीं हैं। हम सोचते हैं कि जेएक्सबी ऑब्जेक्ट फैक्ट्री क्लास को ऑब्जेक्ट फ़ैक्टरी के रूप में पहचान नहीं सकता है बल्कि डेटाटाइप के रूप में।

एक संभावना यह है कि हम जावा 6 में JAXB की आंतरिक संस्करण का उपयोग कर रहे थे था, इसलिए हम सिस्टम संपत्ति -Djava.endorsed.dirs का उपयोग करें और (JAXB-api-2.2.4 तीन जार डाल करने का निर्णय लिया .jar, jaxb-impl-2.2.4.jar और jaxb-xjc-2.2.4.jar) उस पथ में, लेकिन अभी भी काम नहीं कर रहा है।

हमें लगता है कि समस्या यह हो सकती है कि हम ओएसजीआई रनटाइम में और निर्माण प्रक्रिया में जेएक्सबी के एक अलग संस्करण का उपयोग कर रहे हैं, इसलिए जेनरेट कोड संगत नहीं है। लेकिन शायद हम गलत हैं और एक और समस्या है।

क्या आपके पास कोई विचार है?

अग्रिम धन्यवाद।

(संपादित करें: इस बारे में अधिक जानकारी)

हम इस तरह से 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 हमारे ऑब्जेक्ट फैक्ट्री कक्षाओं से टाइप जानकारी प्राप्त करने का प्रयास कर रहा है, जो गलत है। वास्तव में, com.sun.xml.internal.bind.v2.model.impl.ModelBuilder: 314 में, getClassAnnotation() कॉल शून्य देता है लेकिन जब मैं उदाहरण देखता हूं तो मैं एनोटेशन XmlRegistry देख सकता हूं।

बात यह है कि, उस बिंदु पर XmlRegistry.class.getClassLoader() शून्य लौटाता है, लेकिन अगर मैं चलाता हूं (क्लास) सी) .getAnnotations() [0] .annotationType()। GetClassLoader() यह लौटाता है ओएसजीआई बंडल "lib.jaxb" का क्लासलोडर जिसमें मेरे जेएक्सबी जार शामिल हैं, जो सही है।

तो, मुझे लगता है कि हम एक ही समय में XmlRegistry के दो अलग-अलग संस्करणों को लोड कर रहे हैं, एक जेडीके से और दूसरा एक जेएक्सबी 2.2.4 जार से लोड हो रहा है। सवाल यह है: क्यों?

और उन सभी com.sun.xml.internal लोड करने के बजाय, और भी अधिक, * कक्षाएं (जैसे JAXBContextImpl), को com.sun.xml.bind.v2.runtime.JAXBContextImpl को लोड और निष्पादित नहीं किया जाना चाहिए जेएक्सबी जार? डीबग प्रक्रिया के दौरान मैं देख सकता हूं कि यह प्रतिबिंब के साथ कुछ सामान कर रहा है लेकिन मुझे समझ में नहीं आता कि ऐसा क्यों कर रहा है।

+0

जावा एसई 6 का उपयोग करके मैं आपके जेएक्सबी इत्यादि की नवीनतम पैच रिलीज का उपयोग करने की अनुशंसा करता हूं जो JAXB 2.1 का समर्थन करता है जब तक कि कोई विशेष JAXB 2.2 सुविधा न हो जिसे आप उपयोग करने का प्रयास कर रहे हैं। –

+0

क्षमा करें कि मैंने इसका उल्लेख नहीं किया है। जेएक्सबी 2.2.4 में अपग्रेड करने का कारण यह है कि हम अपने जेएक्स-डब्ल्यूएस संस्करण को 2.2.5 तक अपग्रेड कर रहे हैं और यह जेएक्सबी के उस संस्करण पर निर्भर करता है (http://jax-ws.java.net/2.2.5/docs/ ReleaseNotes.html)। अन्यथा हम जेएक्सबी 2.1 का उपयोग कर सकते हैं। – Denian

+0

ऐसा लगता है कि आपका जेएक्सबी इत्यादि गलती से 'ऑब्जेक्ट फैक्ट्री' को डोमेन क्लास के रूप में देख रहा है। आपकी डोमेन कक्षाओं और जेएक्स-डब्ल्यूएस कार्यान्वयन के बीच 'क्लासलोडर' अंतर के कारण' @ XmlRegistry' एनोटेशन की पहचान होने की संभावना अधिकतर है। क्या आप सीधे 'JAXBContext' बना रहे हैं या यह कर रहे जेएक्स-डब्ल्यूएस कार्यान्वयन है? –

उत्तर

2

हमें अंततः इसके लिए एक समाधान मिला।

JAXB प्रलेखन से (JAXB कार्यान्वयन खंड के डिस्कवरी):

http://jaxb.java.net/nonav/2.2.4-1/docs/api/javax/xml/bind/JAXBContext.html

हम में/सेवाओं/javax.xml.bind.JAXBContextMETA-INF में एक संसाधन जोड़ने की कोशिश की सूर्य के आंतरिक कारखाने के बजाय com.sun.xml.bind.v2.ContextFactory के उपयोग को लागू करने के लिए आदेश। यह काम नहीं किया, शायद इसलिए कि हम एक ओएसजीआई बंडल का उपयोग कर रहे हैं। 343:

वैसे भी, के रूप में हम अपने ही classloader उपयोग कर रहे हैं, हम getResourceAsStream() विधि ओवरराइड, कि ContextFinder से कहा जाता है

@Override 
public InputStream getResourceAsStream(String name) 
{ 
    if (name!=null && name.equals("META-INF/services/javax.xml.bind.JAXBContext")) 
    { 
    return new ByteArrayInputStream("com.sun.xml.bind.v2.ContextFactory".getBytes()); 
    } 
    return super.getResourceAsStream(name); 
} 

इस सुंदर समाधान नहीं है बल्कि यह हमारे लिए काम करता है । और वह क्लासलोडर केवल तभी उपयोग किया जाता है जब हम JAXBContext बनाते हैं, यह ठीक होना चाहिए।

2
  1. (, XmlRegistry.class फ़ाइल के लिए खोज उपयोग नहीं) यकीन है कि है कि वहाँ अपने classpath में केवल एक ही @XmlRegistry एनोटेशन करें। शायद गलत एनोटेशन उठाया गया है।

  2. यदि यह काम नहीं करता है, तो अपना खुद का क्लासलोडर बनाएं जो केवल एक कारखाना देखता है। यह जरूरी नहीं होना चाहिए लेकिन कौन जानता है।

  3. JAXBContextImpl.java:436 पर ब्रेकपॉइंट सेट करने का प्रयास करें यह देखने के लिए कि यह किस प्रकार की प्रक्रिया करता है और क्यों।

+0

हाय, देर से उत्तर के लिए खेद है। 1. जैक्सब-एपीआई-2.2.4.jar में एक एक्सएमएल रजिस्ट्री.क्लास है (जो मेरे बंडल के अंदर है "lib.jaxb") और जावा 1.6 classes .jar में। 2. कार्यान्वयन को बदलना मुश्किल है, मैं कोशिश करूंगा कि अगर मैं 3. के साथ सफल नहीं हूं 3. मैं आंतरिक को डीबग कर रहा हूं, लेकिन मुझे मुख्य पोस्ट में अपनी टिप्पणी जोड़ने दें। – Denian

+0

आपके महान प्रयास के लिए धन्यवाद। दुर्भाग्यवश, मैं अपने लीग से बाहर हूं, अब :-(मुझे पूरा यकीन है कि ओएसजीआई/जावा क्लासलोडिंग कैसे करता है (नियम पहले पैरेंट सीएल से लोड करना है, इसलिए जावा कोड कक्षाओं पर प्राथमिकता है ओएसजीआई क्लासपाथ में जोड़ता है)। एक परीक्षण के रूप में, ** बूट ** क्लासपाथ में अपने जेएक्सबी कार्यान्वयन को निर्दिष्ट करने का प्रयास करें (डॉक्स को इसे कैसे सेट करें: http://download.oracle.com/javase/1.3/docs/ tooldocs/win32/migration.html # bootcp) –

+0

हाय हारून, आपके उत्तर के लिए धन्यवाद। मैंने बूटक्लासपैथ में जार जोड़ने की कोशिश की लेकिन इससे कोई फर्क नहीं पड़ता, वही अपवाद फेंक दिया जाता है। – Denian

0

मुझे एक ही समस्या थी, लेकिन एक अलग कारण था। भले ही यह लेखकों की समस्याओं को ठीक न करे, फिर भी मैं उन सभी के लिए यह उत्तर पोस्ट करता हूं, बाद में इस पोस्ट को पढ़ता हूं और मेरे जैसा ही मुद्दा करता हूं।

मैंने इस कंपाइलर-प्लगइन कॉन्फ़िगरेशन का उपयोग किया, जिसमें पैकेज-info.java फ़ाइलों को संकलन से बाहर रखा गया। एक आकर्षण की तरह काम किया सब कुछ बाहर निकालने के बाद! ऐसा लगता है कि जेएक्सबी इन फ़ाइलों में कुछ महत्वपूर्ण परिभाषाओं को शामिल करता है!

टूटी कॉन्फ़िग:

<plugin> 
    <artifactId>maven-compiler-plugin</artifactId> 
     <version>3.0</version> 
     <configuration> 
      <source>1.6</source> 
      <target>1.6</target> 
      <encoding>UTF-8</encoding> 
     <excludes> 
      <exclude>**/package-info.java</exclude> 
     </excludes> 
     <showDeprecation>true</showDeprecation> 
     <showWarnings>true</showWarnings> 
     <fork>false</fork> 
    </configuration> 
</plugin> 

कार्य कॉन्फ़िग:

<plugin> 
     <artifactId>maven-compiler-plugin</artifactId> 
     <version>3.0</version> 
     <configuration> 
      <source>1.6</source> 
      <target>1.6</target> 
      <encoding>UTF-8</encoding> 
      <showDeprecation>true</showDeprecation> 
      <showWarnings>true</showWarnings> 
      <fork>false</fork> 
     </configuration> 
    </plugin> 
0

जब एक वसंत आधारित साबुन वेब सेवा को तैनात करने की कोशिश कर रहा एक ऐसी ही समस्या हुई। मैंने वसंत बीन के contextPaths में एक पैकेज जोड़ा। समस्या यह थी कि एक ही कक्षा अन्य पैकेजों में उसी contextPaths में शामिल थी। मैंने उस पैकेज से उन अन्य वर्गों को बाहर करने के लिए चींटी बिल्ड स्क्रिप्ट को बदल दिया, जिससे मैंने इस मुद्दे को हल किया।

संबंधित मुद्दे