JAX-WS क्लाइंट: स्थानीय WSDL तक पहुँचने का सही रास्ता क्या है?


86

समस्या यह है कि मुझे प्रदान की जाने वाली फ़ाइल से वेब सेवा क्लाइंट बनाने की आवश्यकता है। मैंने इस फ़ाइल को स्थानीय फ़ाइल सिस्टम पर संग्रहीत किया है और, जब मैं WSDL फ़ाइल को सही फ़ाइल सिस्टम फ़ोल्डर में रखता हूं, तो सब कुछ ठीक है। जब मैं इसे सर्वर पर तैनात करता हूं या फ़ाइल सिस्टम फ़ोल्डर से डब्ल्यूएसडीएल को हटाता हूं, तो प्रॉक्सी डब्ल्यूएसडीएल को नहीं ढूंढ सकता है और एक त्रुटि उठाता है। मैंने वेब खोज लिया है और मुझे निम्नलिखित पोस्ट मिल गई हैं, फिर भी मैं यह काम नहीं कर पा रहा हूं:
JAX-WS Loading WSDL jar
http://www.java.net/forum/topic/glassfish/metro से -और-jaxb / ग्राहक-जार-कैंट-ढूंढ-स्थानीय-wsdl-0
http://blog.vinodsingh.com/2008/12/locally-packaged-wsdl.html

मैं नेटबियंस 6.1 का उपयोग कर रहा हूं (यह एक विरासत एप्लिकेशन है जिसे मुझे इस नए वेब सेवा क्लाइंट के साथ अपडेट करना है)। नीचे JAX-WS प्रॉक्सी वर्ग है:

    @WebServiceClient(name = "SOAService", targetNamespace = "http://soaservice.eci.ibm.com/", wsdlLocation = "file:/C:/local/path/to/wsdl/SOAService.wsdl")
public class SOAService
    extends Service
{

    private final static URL SOASERVICE_WSDL_LOCATION;
    private final static Logger logger = Logger.getLogger(com.ibm.eci.soaservice.SOAService.class.getName());

    static {
        URL url = null;
        try {
            URL baseUrl;
            baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");
            url = new URL(baseUrl, "file:/C:/local/path/to/wsdl/SOAService.wsdl");
        } catch (MalformedURLException e) {
            logger.warning("Failed to create URL for the wsdl Location: 'file:/C:/local/path/to/wsdl/SOAService.wsdl', retrying as a local file");
            logger.warning(e.getMessage());
        }
        SOASERVICE_WSDL_LOCATION = url;
    }

    public SOAService(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public SOAService() {
        super(SOASERVICE_WSDL_LOCATION, new QName("http://soaservice.eci.ibm.com/", "SOAService"));
    }

    /**
     * @return
     *     returns SOAServiceSoap
     */
    @WebEndpoint(name = "SOAServiceSOAP")
    public SOAServiceSoap getSOAServiceSOAP() {
        return super.getPort(new QName("http://soaservice.eci.ibm.com/", "SOAServiceSOAP"), SOAServiceSoap.class);
    }

    /**
     * @param features
     *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
     * @return
     *     returns SOAServiceSoap
     */
    @WebEndpoint(name = "SOAServiceSOAP")
    public SOAServiceSoap getSOAServiceSOAP(WebServiceFeature... features) {
        return super.getPort(new QName("http://soaservice.eci.ibm.com/", "SOAServiceSOAP"), SOAServiceSoap.class, features);
    }

}


यह प्रॉक्सी का उपयोग करने के लिए मेरा कोड है:

   WebServiceClient annotation = SOAService.class.getAnnotation(WebServiceClient.class);
   // trying to replicate proxy settings
   URL baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource("");//note : proxy uses "."
   URL url = new URL(baseUrl, "/WEB-INF/wsdl/client/SOAService.wsdl");
   //URL wsdlUrl = this.getClass().getResource("/META-INF/wsdl/SOAService.wsdl"); 
   SOAService serviceObj = new SOAService(url, new QName(annotation.targetNamespace(), annotation.name()));
   proxy = serviceObj.getSOAServiceSOAP();
   /* baseUrl;

   //classes\com\ibm\eci\soaservice
   //URL url = new URL(baseUrl, "../../../../wsdl/SOAService.wsdl");

   proxy = new SOAService().getSOAServiceSOAP();*/
   //updating service endpoint 
   Map<String, Object> ctxt = ((BindingProvider)proxy ).getRequestContext();
   ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);
   ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, WebServiceUrl);

NetBeans ने वेब-inf / wsdl / client / SOAService में WSDL की एक प्रति लगाई है , इसलिए मैं इसे META-INF में भी नहीं जोड़ना चाहता । सेवा वर्ग WEB-INF / classes / com / ibm / eci / soaservice / में हैं और बेसल वैरिएबल में फाइलसिस्टम पूरा पथ समाहित करता है (c: \ path \ to to the \ Project ... \ soaservice)। उपरोक्त कोड त्रुटि उठाता है:

javax.xml.ws.WebServiceException: WSDL को इस पर एक्सेस करने में विफल: फ़ाइल: /WEB-INF/wsdl/client/SOAService.wsdl। यह इसके साथ विफल रहा: \ WEB-INF \ wsdl \ client \ SOAService.wsdl (पथ नहीं मिल सकता)

तो, सबसे पहले, क्या मुझे प्रॉक्सी क्लास के wsdllocation को अपडेट करना होगा? तब मैं WEB-INF / classes / com / ibm / eci / soaservice में SOAService वर्ग को WSDL के लिए \ WEB-INF \ wsdl \ client \ SOAService.wsdl में खोजने के लिए कैसे बताऊं?

EDITED : मुझे यह अन्य लिंक मिला है - http://jianmingli.com/wp/?cat=41 , जो WSDL को क्लासपाथ में डालने के लिए कहते हैं। मुझे यह पूछने में शर्म आ रही है: मैं इसे वेब एप्लिकेशन क्लासपाथ में कैसे डालूं?


इसी तरह का प्रश्न: JAX-WS लोडिंग WSDL जार से
स्लेसके

जवाबों:


117

सबसे अच्छा विकल्प jax-ws-catalog.xml का उपयोग करना है

जब आप स्थानीय WSDL फ़ाइल संकलित करते हैं, तो WSDL स्थान को ओवरराइड करें और इसे कुछ इस तरह सेट करें

http: //localhost/wsdl/SOAService.wsdl

चिंता न करें कि यह केवल एक यूआरआई है और एक यूआरएल नहीं है, जिसका अर्थ है कि आपके पास उस पते पर डब्ल्यूएसडीएल उपलब्ध नहीं है।
आप इसे wsdll से java कंपाइलर के लिए wsdllocation ऑप्शन पास करके कर सकते हैं।

ऐसा करने से आपका प्रॉक्सी कोड बदल जाएगा

static {
    URL url = null;
    try {
        URL baseUrl;
        baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");
        url = new URL(baseUrl, "file:/C:/local/path/to/wsdl/SOAService.wsdl");
    } catch (MalformedURLException e) {
        logger.warning("Failed to create URL for the wsdl Location: 'file:/C:/local/path/to/wsdl/SOAService.wsdl', retrying as a local file");
        logger.warning(e.getMessage());
    }
    SOASERVICE_WSDL_LOCATION = url;
}

सेवा

static {
    URL url = null;
    try {
        URL baseUrl;
        baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");
        url = new URL(baseUrl, "http://localhost/wsdl/SOAService.wsdl");
    } catch (MalformedURLException e) {
        logger.warning("Failed to create URL for the wsdl Location: 'http://localhost/wsdl/SOAService.wsdl', retrying as a local file");
        logger.warning(e.getMessage());
    }
    SOASERVICE_WSDL_LOCATION = url;
}

सूचना फ़ाइल: // URL कंस्ट्रक्टर में http: // में बदल गया।

अब jax-ws-catalog.xml में आता है। बिना jax-ws-catalog.xml jax-ws वास्तव में स्थान से WSDL को लोड करने का प्रयास करेगा

http: //localhost/wsdl/SOAService.wsdl
और असफल रहे, क्योंकि ऐसा कोई डब्ल्यूएसडीएल उपलब्ध नहीं होगा।

लेकिन jax-ws-catalog.xml के साथ जब आप WSDL @ को एक्सेस करने का प्रयास करते हैं तो आप स्थानीय स्तर पर WSDL में jax-ws को रीडायरेक्ट कर सकते हैं।

http: //localhost/wsdl/SOAService.wsdl

यहाँ jax-ws-catalog.xml है

<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
        <system systemId="http://localhost/wsdl/SOAService.wsdl"
                uri="wsdl/SOAService.wsdl"/>
    </catalog>

आप जो कुछ भी कर रहे हैं वह jax-ws बता रहा है कि कब से इसे WSDL से लोड करने की आवश्यकता है

http: //localhost/wsdl/SOAService.wsdl
, इसे स्थानीय पथ wsdl / SOAService.wsdl से लोड करना चाहिए।

अब आपको wsdl / SOAService.wsdl और jax-ws-कैटलॉग.xml कहां लगाना चाहिए? यह मिलियन डॉलर का सवाल है न?
यह आपके एप्लिकेशन जार की META-INF निर्देशिका में होना चाहिए।

ऐसा कुछ है

ABCD.jar  
| __ मेटा-इंफ़    
    | __ jax-ws-catalog.xml  
    | __ wsdl  
        | __ SOAService.wsdl  

इस तरह से आपको अपने क्लाइंट में उस URL को ओवरराइड भी नहीं करना पड़ेगा जो प्रॉक्सी को एक्सेस करता है। डब्लूएसडीएल आपके JAR के भीतर से उठाया गया है, और आप अपने कोड में हार्ड-कोडेड फाइल सिस्टम पथ होने से बचते हैं।

Jax-ws-catalog.xml http://jax-ws.java.net/nonav/2.1.2m1/docs/catalog-support.html पर अधिक जानकारी

उम्मीद है की वो मदद करदे


ठीक है, मैं वेब एप्लिकेशन के भीतर इस तरह से समस्या को हल करने में सक्षम नहीं हूं: मैंने सफलता के बिना वेब-इनस के अंदर wsdl डालने की कोशिश की है, शायद मेरे ज्ञान की कमी के लिए। वैसे भी यह एक जार के साथ काम करता है, इसलिए मैं एक रैपर लाइब्रेरी बनाऊंगा, क्योंकि यह शुरुआत से ही किया जाना चाहिए था। आपके समर्थन के लिए धन्यवाद

मैं इस उत्तर का सफलतापूर्वक उपयोग करने में सक्षम था और मेरा मानना ​​है कि यह अन्य लेखों और ट्यूटोरियल दस्तावेज़ के अन्य विकल्पों की तुलना में बेहतर समाधान है। इसलिए मेरे लिए यह सबसे अच्छा अभ्यास है। मुझे आश्चर्य है कि JAX-WS विषय को कवर करने वाले अन्य आधिकारिक लेखों और ट्यूटोरियल में यह समाधान क्यों नहीं प्रलेखित है।
राहुल खिमसिया

19

एक अन्य दृष्टिकोण जो हमने सफलतापूर्वक लिया है वह है wsimport (चींटी से, एक चींटी कार्य के रूप में) का उपयोग करके WS क्लाइंट प्रॉक्सी कोड उत्पन्न करना और wsdlocation विशेषता को निर्दिष्ट करना।

<wsimport debug="true" keep="true" verbose="false" target="2.1" sourcedestdir="${generated.client}" wsdl="${src}${wsdl.file}" wsdlLocation="${wsdl.file}">
</wsimport>

चूँकि हम इसे एक प्रोजेक्ट w / मल्टीपल WSDLs के लिए चलाते हैं, लिपि गतिशील रूप से $ (wsdl.file) मान को हल करती है जो कि JavaSource लोकेशन (या / src) के सापेक्ष /META-INF/wsdl/YourWebSSNNDddl पर सेट की जाती है। इस बात पर निर्भर करता है कि आपने अपना प्रोजेक्ट कैसे सेट किया है)। बिल्ड प्रॉसेस के दौरान, WSDL और XSDs फ़ाइलों को इस स्थान पर कॉपी किया जाता है और JAR फ़ाइल में पैक किया जाता है। (ऊपर भासकर द्वारा वर्णित समाधान के समान)।

MyApp.jar
|__META-INF
   |__wsdl
      |__YourWebServiceName.wsdl
      |__YourWebServiceName_schema1.xsd
      |__YourWebServiceName_schmea2.xsd

ध्यान दें: सुनिश्चित करें कि WSDL फाइलें किसी भी आयातित XSD के सापेक्ष रेफरल का उपयोग कर रही हैं न कि http URL की:

  <types>
    <xsd:schema>
      <xsd:import namespace="http://valueobject.common.services.xyz.com/" schemaLocation="YourWebService_schema1.xsd"/>
    </xsd:schema>
    <xsd:schema>
      <xsd:import namespace="http://exceptions.util.xyz.com/" schemaLocation="YourWebService_schema2.xsd"/>
    </xsd:schema>
  </types>

में उत्पन्न कोड, हम इस पाते हैं:

/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.2-b05-
 * Generated source version: 2.1
 * 
 */
@WebServiceClient(name = "YourService", targetNamespace = "http://test.webservice.services.xyz.com/", wsdlLocation = "/META-INF/wsdl/YourService.wsdl")
public class YourService_Service
    extends Service
{

    private final static URL YOURWEBSERVICE_WSDL_LOCATION;
    private final static WebServiceException YOURWEBSERVICE_EXCEPTION;
    private final static QName YOURWEBSERVICE_QNAME = new QName("http://test.webservice.services.xyz.com/", "YourService");

    static {
        YOURWEBSERVICE_WSDL_LOCATION = com.xyz.services.webservice.test.YourService_Service.class.getResource("/META-INF/wsdl/YourService.wsdl");
        WebServiceException e = null;
        if (YOURWEBSERVICE_WSDL_LOCATION == null) {
            e = new WebServiceException("Cannot find '/META-INF/wsdl/YourService.wsdl' wsdl. Place the resource correctly in the classpath.");
        }
        YOURWEBSERVICE_EXCEPTION = e;
    }

    public YourService_Service() {
        super(__getWsdlLocation(), YOURWEBSERVICE_QNAME);
    }

    public YourService_Service(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    /**
     * 
     * @return
     *     returns YourService
     */
    @WebEndpoint(name = "YourServicePort")
    public YourService getYourServicePort() {
        return super.getPort(new QName("http://test.webservice.services.xyz.com/", "YourServicePort"), YourService.class);
    }

    /**
     * 
     * @param features
     *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
     * @return
     *     returns YourService
     */
    @WebEndpoint(name = "YourServicePort")
    public YourService getYourServicePort(WebServiceFeature... features) {
        return super.getPort(new QName("http://test.webservice.services.xyz.com/", "YourServicePort"), YourService.class, features);
    }

    private static URL __getWsdlLocation() {
        if (YOURWEBSERVICE_EXCEPTION!= null) {
            throw YOURWEBSERVICE_EXCEPTION;
        }
        return YOURWEBSERVICE_WSDL_LOCATION;
    }

}

शायद यह भी मदद कर सकता है। यह सिर्फ एक अलग दृष्टिकोण है जो "कैटलॉग" दृष्टिकोण का उपयोग नहीं करता है।


मुझे यह तरीका पसंद है ... लेकिन META-INF निर्देशिका क्यों?
इडेडांटे

1
कृपया ध्यान दें कि इसके लिए JAX-WS RI 2.2 के उपयोग की आवश्यकता है, 2.1 नहीं जो डिफ़ॉल्ट रूप से JDK 6 के साथ आता है
ᄂ ᄂ ᄂ

4

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

  1. के रूप में अपने wsdl स्थानीय स्थान संदर्भ बनाओ wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
  2. सही के तहत एक मेटा-इन फ़ोल्डर बनाएँ। META-INF के अंतर्गत किसी फ़ोल्डर में अपनी wsdl फ़ाइल / s डालें, META-INF / wsdl कहें
  3. नीचे के रूप में मेटा-इन के तहत एक xml फ़ाइल jax-ws-कैटलॉग। xml बनाएं

    <catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system"> <system systemId="http://localhost/wsdl/yourwsdlname.wsdl" uri="wsdl/yourwsdlname.wsdl" /> </catalog>

अब अपने जार को पैकेज करें। स्थानीय निर्देशिका के लिए कोई और संदर्भ नहीं, यह सब पैक और भीतर संदर्भित है


4

उन लोगों के लिए जो अभी भी यहां समाधान के लिए आ रहे हैं, सबसे आसान समाधान <wsdlLocation>किसी भी कोड को बदले बिना उपयोग करना होगा । काम के चरण नीचे दिए गए हैं:

  1. अपने wsdl को संसाधन निर्देशिका में रखें जैसे: src/main/resource
  2. Pom फ़ाइल में, wsdlDirectory और wsdlLocation (जैसे कि wsdlLocation की शुरुआत में कोई चूक न करें) दोनों को जोड़ें। जबकि wsdlDirectory का उपयोग कोड उत्पन्न करने के लिए किया जाता है और गतिशील प्रॉक्सी बनाने के लिए wsdlLocation का उपयोग रनटाइम पर किया जाता है।

    <wsdlDirectory>src/main/resources/mydir</wsdlDirectory>
    <wsdlLocation>/mydir/my.wsdl</wsdlLocation>
    
  3. फिर आपके जावा कोड में (बिना arg कंस्ट्रक्टर के):

    MyPort myPort = new MyPortService().getMyPort();
    
  4. पूर्णता के लिए, मैं जनरेट कोड में धाराप्रवाह एपी के साथ यहां पूर्ण कोड जनरेशन पार्ट दे रहा हूं।

    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>2.5</version>
    
    <dependencies>
        <dependency>
            <groupId>org.jvnet.jaxb2_commons</groupId>
            <artifactId>jaxb2-fluent-api</artifactId>
            <version>3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-tools</artifactId>
            <version>2.3.0</version>
        </dependency>
    </dependencies>
    
    <executions>
        <execution>
            <id>wsdl-to-java-generator</id>
            <goals>
                <goal>wsimport</goal>
            </goals>
            <configuration>
                <xjcArgs>
                    <xjcArg>-Xfluent-api</xjcArg>
                </xjcArgs>
                <keep>true</keep>
                <wsdlDirectory>src/main/resources/package</wsdlDirectory>
                <wsdlLocation>/package/my.wsdl</wsdlLocation>
                <sourceDestDir>${project.build.directory}/generated-sources/annotations/jaxb</sourceDestDir>
                <packageName>full.package.here</packageName>
            </configuration>
        </execution>
    </executions>
    


2

आप उन लोगों के लिए जो स्प्रिंग का उपयोग कर रहे हैं, आप केवल क्लासपैथ-प्रोटोकॉल का उपयोग करके किसी भी क्लासपैथ-रिसोर्स का संदर्भ ले सकते हैं। तो wsdlLocation के मामले में, यह बन जाता है:

<wsdlLocation>classpath:META-INF/webservice.wsdl</wsdlLocation>

ध्यान दें कि मानक जावा व्यवहार नहीं है। इसे भी देखें: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html


0

था सटीक एक ही समस्या है कि इस के साथ साथ वर्णित है। कोई फर्क नहीं पड़ता कि मैंने क्या किया, उपरोक्त उदाहरणों के बाद, मेरी WSDL फ़ाइल (एक वेब सर्वर से हमारे मामले में) के स्थान को बदलने के लिए, यह अभी भी सर्वर प्रक्रिया के स्रोत ट्री के भीतर एम्बेडेड मूल स्थान को संदर्भित कर रहा था।

MANY घंटों के बाद यह डिबग करने की कोशिश कर रहा था, मैंने देखा कि अपवाद हमेशा एक ही लाइन (मेरे मामले में 41) से फेंका जा रहा था। अंत में आज सुबह, मैंने अपने सोर्स क्लाइंट कोड को सिर्फ हमारे ट्रेड पार्टनर को भेजने का फैसला किया ताकि वे कम से कम यह समझ सकें कि कोड कैसा दिखता है, लेकिन शायद अपना खुद का निर्माण करें। अपने सदमे और डरावनी स्थिति के लिए मैंने अपने क्लाइंट स्रोत ट्री के भीतर अपने .java फ़ाइलों के साथ मिश्रित वर्ग फ़ाइलों का एक गुच्छा पाया। कितना विचित्र !! मुझे संदेह है कि ये JAX-WS क्लाइंट बिल्डर टूल का एक बायप्रोडक्ट थे।

एक बार जब मैंने उन मूर्खतापूर्ण .class फ़ाइलों को टैप किया और क्लाइंट कोड का पूर्ण स्वच्छ और पुनर्निर्माण किया, तो सब कुछ पूरी तरह से काम करता है !! Redonculous !!

YMMV, एंड्रयू

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.