2015-09-22 7 views
6

मेरे पास जैक्सडब्लूएस वेब सेवा क्लाइंट है जो वर्षों से जावा 6 में सफलतापूर्वक चल रहा है। अब जब जावा संस्करण 8 करने के लिए उन्नत किया गया था, हम NullPointerException हो रही है जब पोर्टजावा 6 के लिए जैक्सडब्ल्यूएस webservice क्लाइंट जावा 8 में काम नहीं कर रहा है 0

java.lang.NullPointerException 
    at com.sun.xml.internal.ws.client.ClientContainer$1.getResource(Unknown Source) 
    at com.sun.xml.internal.ws.assembler.MetroConfigLoader.locateResource(Unknown Source) 
    at com.sun.xml.internal.ws.assembler.MetroConfigLoader.locateResource(Unknown Source) 
    at com.sun.xml.internal.ws.assembler.MetroConfigLoader.init(Unknown Source) 
    at com.sun.xml.internal.ws.assembler.MetroConfigLoader.<init>(Unknown Source) 
    at com.sun.xml.internal.ws.assembler.TubelineAssemblyController.getTubeCreators(Unknown Source) 
    at com.sun.xml.internal.ws.assembler.MetroTubelineAssembler.createClient(Unknown Source) 
    at com.sun.xml.internal.ws.client.Stub.createPipeline(Unknown Source) 
    at com.sun.xml.internal.ws.client.Stub.<init>(Unknown Source) 
    at com.sun.xml.internal.ws.client.Stub.<init>(Unknown Source) 
    at com.sun.xml.internal.ws.client.Stub.<init>(Unknown Source) 
    at com.sun.xml.internal.ws.client.sei.SEIStub.<init>(Unknown Source) 
    at com.sun.xml.internal.ws.client.WSServiceDelegate.getStubHandler(Unknown Source) 
    at com.sun.xml.internal.ws.client.WSServiceDelegate.createEndpointIFBaseProxy(Unknown Source) 
    at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(Unknown Source) 
    at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(Unknown Source) 
    at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(Unknown Source) 
    at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(Unknown Source) 
    at javax.xml.ws.Service.getPort(Unknown Source) 
    at myclient.stub.MyService.<init>(MyService.java:38) 

मैं जावा 7 संस्करण 1.7.0_80 साथ इसे चलाने की कोशिश की है हो रही है और वहाँ यह भी काम करता है लेकिन जावा के पहले संस्करण 8 कारणों इस अपवाद।

मैं कुछ समय से इस के साथ अपने सिर को टक्कर लगी हूं, इसलिए यदि कोई मुझे कोई फिक्स दे सकता है कि इसे ठीक करना शुरू करना है तो यह वास्तव में बहुत अच्छा होगा।

यहां डब्ल्यूएसडीएल है, मैंने इसे थोड़ा संपादित किया क्योंकि यह मेरी सेवा नहीं है लेकिन उम्मीद है कि यह पर्याप्त है?

<?xml version="1.0" encoding="utf-8" standalone="no"?> 
<wsdl:definitions xmlns:ns1="http://www.dummyservice/sample/interface" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
     xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Sample" 
     targetNamespace="http://www.dummyservice/sample/interface"> 
    <wsdl:types> 
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
    targetNamespace="http://www.dummyservice/sample/interface" xmlns="http://www.dummyservice/sample/interface" 
    elementFormDefault="qualified" jaxb:version="2.0"> 
     <xs:element name="PersonQuery"> 
     <xs:complexType> 
      <xs:sequence> 
      <xs:element name="system" type="xs:string" /> 
      <xs:element name="user" type="xs:string" /> 
      </xs:sequence> 
     </xs:complexType> 
     </xs:element> 
     <xs:element name="PersonReply"> 
     <xs:complexType> 
      <xs:sequence> 
      <xs:element name="Header" type="HeaderType" /> 
      <xs:element name="person" type="PersonType" minOccurs="0" maxOccurs="1" /> 
      <xs:element name="address" type="AddressType" minOccurs="0" maxOccurs="unbounded" /> 
      </xs:sequence> 
     </xs:complexType> 
     </xs:element> 
     <xs:complexType name="HeaderType"> 
     <xs:sequence> 
      <xs:element name="tila" type="StatusType" /> 
     </xs:sequence> 
     </xs:complexType> 
     <xs:simpleType name="StatusType"> 
     <xs:annotation> 
      <xs:appinfo> 
      <jaxb:typesafeEnumClass> 
       <jaxb:typesafeEnumMember name="SUCCESS" value="0001" /> 
       <jaxb:typesafeEnumMember name="FAIL" value="0000" /> 
      </jaxb:typesafeEnumClass> 
      </xs:appinfo> 
     </xs:annotation> 
     <xs:restriction base="xs:string"> 
      <xs:enumeration value="0000" /> 
      <xs:enumeration value="0001" /> 
     </xs:restriction> 
     </xs:simpleType> 
     <xs:complexType name="PersonType"> 
     <xs:sequence> 
      <xs:element name="firstname" type="xs:string" minOccurs="0" /> 
      <xs:element name="lastname" type="xs:string" minOccurs="0" /> 
     </xs:sequence> 
     </xs:complexType> 
     <xs:complexType name="AddressType"> 
     <xs:sequence> 
      <xs:element name="addresstype" type="AddresstypeType" minOccurs="0" /> 
      <xs:element name="streetaddress" type="xs:string" minOccurs="0" /> 
      <xs:element name="city" type="xs:string" minOccurs="0" /> 
      <xs:element name="postalcode" type="xs:string" minOccurs="0" /> 
     </xs:sequence> 
     </xs:complexType> 
     <xs:simpleType name="AddresstypeType"> 
     <xs:annotation> 
      <xs:appinfo> 
      <jaxb:typesafeEnumClass> 
       <jaxb:typesafeEnumMember name="HOME" value="001" /> 
       <jaxb:typesafeEnumMember name="OFFICE" value="002" /> 
      </jaxb:typesafeEnumClass> 
      </xs:appinfo> 
     </xs:annotation> 
     <xs:restriction base="xs:string"> 
      <xs:enumeration value="001" /> 
      <xs:enumeration value="002" /> 
     </xs:restriction> 
     </xs:simpleType> 
    </xs:schema> 
    </wsdl:types> 
    <wsdl:message name="PersonQueryOperationRequest"> 
    <wsdl:part element="ns1:PersonQuery" name="parameters" /> 
    </wsdl:message> 
    <wsdl:message name="PersonQueryOperationResponse"> 
    <wsdl:part element="ns1:PersonReply" name="parameters" /> 
    </wsdl:message> 
    <wsdl:portType name="SamplePort"> 
    <wsdl:operation name="PersonQueryOperation"> 
     <wsdl:input message="ns1:PersonQueryOperationRequest" /> 
     <wsdl:output message="ns1:PersonQueryOperationResponse" /> 
    </wsdl:operation> 
    </wsdl:portType> 
    <wsdl:binding name="SampleSOAP" type="ns1:SamplePort"> 
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> 
    <wsdl:operation name="PersonQueryOperation"> 
     <soap:operation soapAction="http://www.dummyservice/sample/interface/SampleOperation" /> 
     <wsdl:input> 
     <soap:body use="literal" /> 
     </wsdl:input> 
     <wsdl:output> 
     <soap:body use="literal" /> 
     </wsdl:output> 
    </wsdl:operation> 
    </wsdl:binding> 
    <wsdl:service name="SampleService"> 
    <wsdl:port binding="ns1:SampleSOAP" name="Sample"> 
     <soap:address location="https://127.0.0.1/data/ws" /> 
    </wsdl:port> 
    </wsdl:service> 
</wsdl:definitions> 

संपादित करें: कक्षा लोड करने की समस्या, दोनों संदर्भ वर्ग लोडर और वर्ग 'वर्ग लोडर प्रतीत हो रहा है कि ClientContainer में अशक्त हैं।

private final ResourceLoader loader = new ResourceLoader() { 
public URL More ...getResource(String resource) throws MalformedURLException { 
     ClassLoader cl = Thread.currentThread().getContextClassLoader(); 
    if (cl == null) { 
     cl = this.getClass().getClassLoader(); 
    } 
    return cl.getResource("META-INF/"+resource); 
} 
}; 

हम स्पष्ट रूप से लागू ws फोन यह काम करना शुरू करने से पहले संदर्भ वर्ग लोडर करने के लिए सिस्टम वर्ग लोडर सेट करते हैं। लेकिन क्या यह इसके लिए अच्छा तय है? मैं सोच रहा हूं कि इसने जावा 8 में क्यों काम करना बंद कर दिया है और क्या यह उनके डब्ल्यूएस-कार्यान्वयन में एक मुद्दा हो सकता है?

सादर,

Janne

+0

क्या आप अपना डब्लूएसडीएल शामिल करने के लिए अपना प्रश्न संपादित कर सकते हैं, तो हम इस मुद्दे को फिर से बनाने का प्रयास कर सकते हैं? – VGR

+0

मैंने डब्लूएसडीएल को शामिल किया है, मुझे इसे मूल से अलग करने के लिए इसे संपादित करना था, लेकिन उम्मीद है कि यह ठीक है। –

+0

यह एकमात्र तरीका [उस विधि] जैसा दिखता है (http://grepcode.com/file/repository.grepcode।com/java/root/jdk/openjdk/8u40-b25/com/sun/xml/internal/ws/client/ClientContainer.java # ClientContainer.0loader) NullPointerException को फेंक सकता है जब वर्ग क्लासलोडर द्वारा लोड किया जाता है (तब से [ सिस्टम क्लासलोडर को इंगित करने के लिए जावा को शून्य वापस करने की अनुमति है] (http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getClassLoader--))। आप किस ओएस पर चल रहे हैं? क्या आपने जावा के नवीनतम संस्करण का उपयोग करने की कोशिश की है? – VGR

उत्तर

1

वेब सेवा ग्राहक के लिए स्टब्स Java8 में फिर से पैदा करने की कोशिश करो।

आम तौर पर हम स्टब्स का एक जार उत्पन्न करते हैं और इसे कक्षा में डाल देते हैं। यह देखते हुए कि जावा पिछड़ा संगत है, हम उच्च संस्करण में अपग्रेड करते समय जार को पुन: उत्पन्न करने के इस चरण को छोड़ देते हैं।

लेकिन जावा 6 & 7 के लिए यह काम कर रहा है और केवल जावा 8 में विफल रहा है, मैं जावा 8 की पिछली संगतता में किसी भी गड़बड़ी को रद्द करने के लिए फिर से स्टब्स उत्पन्न करने की अनुशंसा करता हूं।

+0

मैंने उन्हें जावा 8 के साथ उत्पन्न किया है लेकिन इसका कोई प्रभाव नहीं है। –

4

हम जावा 6 से जावा 8 तक अपग्रेड करने के बाद भी इस समस्या (एक ही स्टैक ट्रेस और सभी) को देख रहे हैं। मैं पहले अपना समाधान पोस्ट करूंगा, इसके बाद अतिरिक्त स्पष्टीकरण होगा।

हमारे लिए, मुख्य शर्तों के तहत इस समस्या तब होती है है:

  1. जावा 8 एक Windows कार्यक्रम के भीतर से jvm.dll के माध्यम से एक एम्बेडेड JVM के रूप में चल रहा है। मैंने स्टैंडअलोन जावा 8 जेवीएम में चल रही समस्या को पुन: पेश करने का प्रयास किया और मैं इसे नहीं कर सका। हालांकि समस्या का निदान करने में स्टैंडअलोन चलाना बहुत उपयोगी था।
  2. किसी JAX-WS वेब सेवा से कनेक्शन प्रारंभ करने की प्रॉक्सी विधि का उपयोग करना, जो सर्वर पक्ष पर होस्ट किए गए WSDL का उपयोग करके क्लाइंट साइड पर गतिशील रूप से स्टब बनाता है।

वर्कअराउंड:

जब आप कॉल Service.getPort(Class<T>) लिए यह अपने आप ही धागे में किया जाना चाहिए आह्वान, धागे से अलग आप कॉल पहले से में चल रहा था। यह आपके लिए क्या अनुमति देता है क्लासलोडर को उस थ्रेड पर क्लासलोडर को सेट करने का अवसर है जो बूटस्ट्रैप क्लासलोडर नहीं है, जो ClientContainer.java में समस्या का क्रूक्स है (नीचे उस पर अधिक स्पष्टीकरण)।यहां कुछ नमूना कोड है जो हमारे लिए काम कर रहा है। आपको अपनी जरूरतों के अनुरूप इसे संशोधित करना होगा।

public class YourClass { 
    private YourWebService yourWebService; 

    // You may want to synchronize on this method depending on your use case 
    public YourWebService getYourWebService() { 
    if (this.yourWebService == null) { 
     // We create a thread so that we can set the ClassLoader 
     Thread t = new Thread() { 
     public void run() { 
      synchronized(this) { 
      // Get the string of your webservice WSDL from somewhere 
      String url = "http://YOURHOST:YOURPORT/your-web-service/YourWebService?wsdl"; 
      URL srvUrl = null; 
      try { 
       srvUrl = new URL(url); 
      } catch (MalformedURLException ex) { 
       throw new RuntimeException(String.format("Malformed URL: %s", url), ex); 
      } 

      QName qName = new QName("your-webservice-namespace", "YourWebServiceName"); 
      Service service = Service.create(srvUrl, qName); 
      this.yourWebService = service.getPort(YourWebService.class); 
      notify(); 
      } 
     } 
     }; 

     // Thread.currentThread().getContextClassloader() 
     // returns null in com.sun.xml.internal.ws.client.ClientContainer. 
     // (See http://hg.openjdk.java.net/jdk8/jdk8/jaxws/file/d03dd22762db/src/share/jaxws_classes/com/sun/xml/internal/ws/client/ClientContainer.java, lines 39-47) 
     // To work around that, I force setting of the ContextClassLoader 
     // on this thread (in which the Service.getPort() method will run) so 
     // that when ClientContainer calls Thread.currentThread().getContextClassLoader(), it doesn't get a null 
     // (i.e., the bootstrap classloader). 
     // 
     t.setContextClassLoader(YourClass.class.getClassLoader()); 
     t.start(); 
     // Wait until above thread completes in order to return yourWebService 
     synchronized(t) { 
     try { 
      t.wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     } 
    } 

    return this.yourWebService; 
    } 
} 

अतिरिक्त पृष्ठभूमि और विवरण:

हमारे लिए इस निदान में कठिनाई यह है कि समस्या केवल एक Windows उत्पाद है जो एक एम्बेडेड JVM की शुरूआत के अंदर हुआ था। उस जेवीएम पर remote debugging के बिना, समस्या के निचले भाग तक पहुंचने में काफी समय लगेगा। एक बार मैंने देखा कि 1) जब मैंने एक ही कोड चलाया जो एक स्टैंडअलोन जेवीएम (विंडोज़ उत्पाद के बाहर) के अंदर Service.getPort(Class<T>) पर कॉल को आमंत्रित करता है, और 2) ClientContainer कक्षा वर्तमान थ्रेड के क्लासलोडर को प्राप्त करने में सक्षम थी और 3) कि क्लासलोडर वापस बूटस्ट्रैप क्लासलोडर नहीं था (यानी, null नहीं), इससे मुझे एहसास हुआ कि मुझे यह सुनिश्चित करने का एक तरीका मिलना था कि ClientContainer थ्रेड जो बूटस्ट्रैप क्लासलोडर नहीं ले रहा था। तब लक्ष्य यह देखने के लिए चला गया कि क्या मुझे ClientContainer कोड द्वारा हल किए गए क्लासलोडर को बदलने का कोई तरीका मिल सकता है।

ClientContainer स्रोत: ClientContainer स्रोत वहाँ एक classloader को हल करने दो प्रयास कर रहे हैं कि में http://hg.openjdk.java.net/jdk8/jdk8/jaxws/file/d03dd22762db/src/share/jaxws_classes/com/sun/xml/internal/ws/client/ClientContainer.java

सूचना। समस्या यह है कि अगर उन प्रयासों की दोनों बूटस्ट्रैप classloader लौटने के लिए, एक NullPointerException cl के बाद लाइन 45 पर परिणाम होगा अशक्त हो जाएगा:

cl.getResource("META-INF/"+resource); 

इस तरीके को सुनिश्चित करता है कि classloader ClientContainer कोड द्वारा हल classloader हो जाएगा कि आप अपने धागे पर सेट करते हैं। https://java.net/jira/browse/JAX_WS-1178

1

मैं जावा 8. के ​​उन्नयन @ 2AGuy का जवाब एक बहुत मदद करता है के बाद एक ही समस्या भर में आया था:

मैं JAX-WS टीम यहां समस्या की जांच करने के लिए एक टिकट का मामला दर्ज किया। हालांकि, समस्या मेरे लिए मैक और लिनक्स दोनों पर चल रही थी। और समस्या को हल करने के लिए एक सरल संस्करण हो सकता है। आपका कोड getPort() कॉल करने से पहले रेखा से नीचे पर अमल कर सकते हैं:

Thread.currentThread().setContextClassLoader(XXX.class.getClassLoader());

यह हो सकता है जिसे आप यह निर्धारित करने के लिए बूटस्ट्रैप वर्ग लोडर से धागा संदर्भ वर्ग लोडर की जगह लेगा, भूमि के ऊपर के बिना बस के लिए एक नया धागा बनाने के लिए क्लासलोडर सेट करें।

इसका मूल कारण अभी भी मेरे लिए एक रहस्य है। मेरा संदेह यह है कि एक एसओएपी सेवा क्लाइंट प्रॉक्सी (दस्तावेज संदर्भ में एक सर्विस एंडपॉइंट प्रॉक्सी) बनाने के लिए धागा मुख्य धागा है या इसके द्वारा बनाया गया है, जिसका क्लासलोडर बूटस्ट्रैप क्लास लोडर है, जिसे JVM प्रारंभ होने पर सबसे शुरुआती चरण में लोड किया जा रहा है। Class#getClassLoader() के लिए जावा डॉक के आधार पर, एक नल पॉइंटर दिखाई देता है।

कुछ कार्यान्वयन बूटस्ट्रैप क्लास लोडर का प्रतिनिधित्व करने के लिए शून्य का उपयोग कर सकते हैं। यदि यह वर्ग बूटस्ट्रैप क्लास लोडर द्वारा लोड किया गया था तो यह विधि इस तरह के कार्यान्वयन में शून्य हो जाएगी।

+1

उस आदमी को एक कुकी दे दो! –

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