कैसे एक CXF या JAX-WS उत्पन्न webservice ग्राहक में WSDL स्थान निर्दिष्ट करने की आवश्यकता से बचने के लिए?


165

जब मैं CXF से wsdl2java (जो wsimport के समान कुछ उत्पन्न करता है) का उपयोग करके एक webservice क्लाइंट उत्पन्न करता हूं, मावेन के माध्यम से, मेरी सेवाएं इस तरह कोड के साथ शुरू होती हैं:

@WebServiceClient(name = "StatusManagement", 
                  wsdlLocation = "c:/some_absolute_path_to_a_wsdl_file.wsdl",
                  targetNamespace = "http://tempuri.org/") 
public class StatusManagement extends Service {

    public final static URL WSDL_LOCATION;
    public final static QName SERVICE = new QName("http://tempuri.org/", "StatusManagement");
    public final static QName WSHttpBindingIStatus = new QName("http://tempuri.org/", "WSHttpBinding_IStatus");
    static {
        URL url = null;
        try {
            url = new URL("c:/some_absolute_path_to_a_wsdl_file.wsdl");
        } catch (MalformedURLException e) {
            System.err.println("Can not initialize the default wsdl from c:/some_absolute_path_to_a_wsdl_file.wsdl");
            // e.printStackTrace();
        }
        WSDL_LOCATION = url;
    }

हार्डकॉस्ट निरपेक्ष पथ वास्तव में बेकार है। उत्पन्न वर्ग मेरा के अलावा किसी अन्य कंप्यूटर में काम नहीं करेगा।

पहला विचार WSDL फ़ाइल (प्लस सब कुछ जो आयात करता है, अन्य WSDLs और XSDs) को कहीं-कहीं जार-फ़ाइल में डालना और इसे वर्गपाठ करना है। लेकिन हम इससे बचना चाहते हैं। चूंकि डब्ल्यूएसडीएल और एक्सएसडीएस में स्थित सीएक्सएफ और जेएक्सबी द्वारा यह सब कुछ उत्पन्न किया गया था, इसलिए हमें डब्ल्यूएसडीएल को रनटाइम के बारे में जानने की आवश्यकता नहीं है।

WsdlLocation विशेषता को WSDL स्थान को ओवरराइड करने का इरादा है (कम से कम यह वही है जिसे मैंने कहीं पढ़ा है), और यह डिफ़ॉल्ट मान "" है। चूँकि हम मावेन का उपयोग कर रहे हैं, हमने <wsdlLocation></wsdlLocation>wsdlLocation को खाली छोड़ने के लिए स्रोत जनरेटर को मजबूर करने के लिए CXF के विन्यास में शामिल करने की कोशिश की। हालाँकि, यह केवल XML टैग को अनदेखा करता है क्योंकि यह खाली है। हम एक बहुत बदसूरत शर्मनाक हैक किया, का उपयोग कर <wsdlLocation>" + "</wsdlLocation>

यह अन्य स्थानों को भी बदलता है:

@WebServiceClient(name = "StatusManagement", 
                  wsdlLocation = "" + "",
                  targetNamespace = "http://tempuri.org/") 
public class StatusManagement extends Service {

    public final static URL WSDL_LOCATION;
    public final static QName SERVICE = new QName("http://tempuri.org/", "StatusManagement");
    public final static QName WSHttpBindingIStatus = new QName("http://tempuri.org/", "WSHttpBinding_IStatus");
    static {
        URL url = null;
        try {
            url = new URL("" + "");
        } catch (MalformedURLException e) {
            System.err.println("Can not initialize the default wsdl from " + "");
            // e.printStackTrace();
        }
        WSDL_LOCATION = url;
    }

तो, मेरे सवाल हैं:

  1. क्या हमें वास्तव में एक डब्ल्यूएसडीएल स्थान की आवश्यकता है, भले ही सभी वर्ग सीएक्सएफ और जेएक्सबी द्वारा उत्पन्न किए गए थे? यदि हाँ, तो क्यों?

  2. अगर हमें वास्तव में डब्ल्यूएसडीएल स्थान की आवश्यकता नहीं है, तो सीएक्सएफ बनाने और इसे पूरी तरह से बचने के लिए उचित और साफ तरीका क्या है?

  3. उस हैक से हमें क्या दुष्प्रभाव हो सकते हैं? हम अभी भी यह देखने के लिए परीक्षण नहीं कर सकते हैं कि क्या होता है, इसलिए यदि कोई अग्रिम में कह सकता है, तो यह अच्छा होगा।

जवाबों:


206

मैंने आखिरकार आज इस सवाल का सही जवाब खोज लिया।

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>${cxf.version}</version>
    <executions>
        <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration> 
                <sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
                <wsdlOptions>
                    <wsdlOption>
                        <wsdl>${project.basedir}/src/main/resources/wsdl/FooService.wsdl</wsdl>
                        <wsdlLocation>classpath:wsdl/FooService.wsdl</wsdlLocation>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
        </execution>
    </executions>
</plugin>

सूचना है कि मैं में मूल्य पहले से जुड़ा हुआ है wsdlLocationके साथ classpath:। यह प्लगइन बताता है कि wsdl एक निरपेक्ष पथ के बजाय क्लासपाथ पर होगा। तो यह इस तरह कोड उत्पन्न करेगा:

@WebServiceClient(name = "FooService", 
                  wsdlLocation = "classpath:wsdl/FooService.wsdl",
                  targetNamespace = "http://org/example/foo") 
public class Foo_Service extends Service {

    public final static URL WSDL_LOCATION;

    public final static QName SERVICE = new QName("http://org/example/foo", "Foo");
    public final static QName FooSOAPOverHTTP = new QName("http://org/example/foo", "Foo_SOAPOverHTTP");
    static {
        URL url = Foo_Service.class.getClassLoader().getResource("wsdl/FooService.wsdl");
        if (url == null) {
            java.util.logging.Logger.getLogger(Foo_Service.class.getName())
                .log(java.util.logging.Level.INFO, 
                     "Can not initialize the default wsdl from {0}", "classpath:wsdl/FooService.wsdl");
        }       
        WSDL_LOCATION = url;
    }

ध्यान दें कि यह केवल संस्करण 2.4.1 या नए cxf-codegen-plugin के साथ काम करता है।


8
CXF के बजाय JAX मावेन प्लगइन का उपयोग करते समय, लाइन classpath:में छोड़ें <wsdlLocation...
12:14

क्या किसी को उपरोक्त विधि द्वारा उत्पन्न कोड के साथ नामस्थान समस्या का सामना करना पड़ रहा है?
नरेंद्र जग्गी

यदि आपके पास कई हैं तो क्या आपको व्यक्तिगत रूप से प्रत्येक wsdl को सूचीबद्ध करना होगा? क्या इससे बचना संभव है?
pitseeker

21

हम प्रयोग करते हैं

wsdlLocation = "WEB-INF/wsdl/WSDL.wsdl"

दूसरे शब्दों में, क्लासपाथ के सापेक्ष एक पथ का उपयोग करें।

मेरा मानना ​​है कि WSDL को मार्शल / अनमरशाल के दौरान संदेशों के सत्यापन के लिए रनटाइम की आवश्यकता हो सकती है।


17

org.jvnet.jax-ws-commons:jaxws-maven-pluginबिल्ड-टाइम पर WSDL से क्लाइंट जेनरेट करने के लिए उपयोग करने वालों के लिए:

  • डब्लूएसडीएल को अपने में कहीं रखें src/main/resources
  • के साथ उपसर्ग करेंwsdlLocationclasspath:
  • के wsdlLocationसाथ उपसर्ग करें/

उदाहरण:

  • WSDL में संग्रहीत किया जाता है /src/main/resources/foo/bar.wsdl
  • jaxws-maven-pluginसाथ कॉन्फ़िगर करें <wsdlDirectory>${basedir}/src/main/resources/foo</wsdlDirectory>और<wsdlLocation>/foo/bar.wsdl</wsdlLocation>

"क्लासस्पैथ के साथ wsdlLocation" का उपसर्ग क्यों नहीं करते हैं, मैं इसका उपयोग करता हूं और यह काम करता है
मोहम्मद सदेघ रफ़ी

9

1) कुछ मामलों में, हाँ। यदि WSDL में नीतियां और ऐसी चीजें हैं जो रनटाइम व्यवहार को निर्देशित करती हैं, तो WSDL को रनटाइम की आवश्यकता हो सकती है। नीति संबंधी चीजों और इस तरह की कलाकृतियां उत्पन्न नहीं की जाती हैं। इसके अलावा, कुछ अस्पष्ट आरपीसी / लिटरल मामलों में, सभी नामस्थानों की जरूरत नहीं है जो उत्पन्न कोड (प्रति युक्ति) में आउटपुट हैं। इस प्रकार, उनके लिए wsdl की आवश्यकता होगी। हालांकि अस्पष्ट मामले।

2) मैंने सोचा था कि कुछ काम करेगा। सीएक्सएफ का क्या संस्करण? यह एक बग की तरह लगता है। आप वहां (बस रिक्त स्थान) एक खाली स्ट्रिंग की कोशिश कर सकते हैं। यकीन नहीं होता कि काम करता है या नहीं। उस ने कहा, अपने कोड में, आप WSDL URL लेने वाले कंस्ट्रक्टर का उपयोग कर सकते हैं और बस शून्य पास कर सकते हैं। Wsdl का उपयोग नहीं किया जाएगा।

3) ऊपर की सीमाएँ।


यह नवीनतम CXF 2.3.1 है। 8 दिन पहले ही जारी किया गया। पासिंग नल एक अच्छा विचार है, मुझे यह स्पष्ट उत्तर पहले देखना चाहिए। मैं अभी भी रिक्त स्थान की कोशिश करूंगा।
विक्टर स्टैफुसा

नहीं, रिक्त स्थान कुछ भी नहीं के रूप में ही करता है। यानी: XML टैग को पूरी तरह से नजरअंदाज कर दिया गया है।
विक्टर स्टैफुसा

5

मैं उत्पन्न करने में सक्षम था

static {
    WSDL_LOCATION = null;
}

ps फ़ाइल को कॉन्फ़िगर करके wsdlurl के लिए एक अशक्त है:

    <plugin>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-codegen-plugin</artifactId>
        <executions>
            <execution>
                <id>generate-sources</id>
                <phase>generate-sources</phase>
                <configuration>
                    <sourceRoot>${basedir}/target/generated/src/main/java</sourceRoot>
                    <wsdlOptions>
                        <wsdlOption>
                            <wsdl>${basedir}/src/main/resources/service.wsdl</wsdl>
                            <extraargs>
                                <extraarg>-client</extraarg>
                                <extraarg>-wsdlLocation</extraarg>
                                <wsdlurl />
                            </extraargs>
                        </wsdlOption>
                    </wsdlOptions>
                </configuration>
                <goals>
                    <goal>wsdl2java</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

2
इस समाधान ने मेरे लिए CXF 3.1.0 के साथ काम नहीं किया। एक त्रुटि प्राप्त हुई। org.apache.cxf.tools.common.toolspec.parser.BadUsageException: अनपेक्षित विकल्प: -sdlLocation
चंद्रू

4

क्या यह संभव है कि आप wsdl2java का उपयोग करने से बच सकते हैं? आप सीधे अपने सोप वेब सेवा को लागू करने के लिए सीएक्सएफ फ्रंटएंड एपीआई का उपयोग कर सकते हैं। एकमात्र पकड़ यह है कि आपको अपने ग्राहक के अंत में अपने एसईआई और वीओ बनाने की आवश्यकता है। यहाँ एक नमूना कोड है।

package com.aranin.weblog4j.client;

import com.aranin.weblog4j.services.BookShelfService;
import com.aranin.weblog4j.vo.BookVO;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class DemoClient {
    public static void main(String[] args){
        String serviceUrl = "http://localhost:8080/weblog4jdemo/bookshelfservice";
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(BookShelfService.class);
        factory.setAddress(serviceUrl);
        BookShelfService bookService = (BookShelfService) factory.create();

        //insert book
        BookVO bookVO = new BookVO();
        bookVO.setAuthor("Issac Asimov");
        bookVO.setBookName("Foundation and Earth");

        String result = bookService.insertBook(bookVO);

        System.out.println("result : " + result);

        bookVO = new BookVO();
        bookVO.setAuthor("Issac Asimov");
        bookVO.setBookName("Foundation and Empire");

        result = bookService.insertBook(bookVO);

        System.out.println("result : " + result);

        bookVO = new BookVO();
        bookVO.setAuthor("Arthur C Clarke");
        bookVO.setBookName("Rama Revealed");

        result = bookService.insertBook(bookVO);

        System.out.println("result : " + result);

        //retrieve book

        bookVO = bookService.getBook("Foundation and Earth");

        System.out.println("book name : " + bookVO.getBookName());
        System.out.println("book author : " + bookVO.getAuthor());

    }
}

आप पूरा ट्यूटोरियल यहां देख सकते हैं http://weblog4j.com/2012/05/01/developing-soap-web-service-using-apache-cxf/


2
डब्लूएसडीएल फाइलें बेहद जटिल थीं, इसलिए हमने संगतता सुनिश्चित करने के तरीके के रूप में ऑटोजेनरेशन का उपयोग किया। ऑटोजेनरेशन ने कुछ समान रूप से जटिल वीओ और एसईआई बनाए। हमने अलग-अलग डोमेन ऑब्जेक्ट का उपयोग करने के लिए चुना है जो पूरी तरह से ऑटोजेनरेटेड लोगों के लिए डिकॉउन्डेड हैं, इसलिए हमने ऑटोगेनरेशन के साथ हस्तक्षेप नहीं किया और न ही इसे प्रतिबंधित या संचालित किया। ऑटोजेनरेटेड VOs का उपयोग केवल सेवा संचार के संदर्भ में किया गया था और हमने उन्हें यथासंभव अल्पकालिक रखा। दूसरे शब्दों में, हमारी एक चिंता यह है कि सभी VO को मैन्युअल रूप से कोड और प्रबंधित करने की आवश्यकता से बचें।
विक्टर स्टैफुसा

2
मैं विक्टर के साथ सहमत हूं, क्योंकि VO मैन्युअल रूप से बनाए रखने के लिए समय की बर्बादी हो सकती है, और मतभेदों का खतरा, कम या ज्यादा दिखाई और योग्य हो सकता है .. यही वास्तव में wsdl2java का उद्देश्य है, इसलिए यह उपयोगी और सुरक्षित है!
डोनाटेलो

4

सीएक्सएफ 3.1.7 के लिए अपडेट

मेरे मामले में मैंने WSDL फाइलों को अंदर डाला src/main/resourcesऔर इस पथ को ग्रहण में मेरी Srouces में जोड़ दिया (प्रोजेक्ट पर राइट क्लिक करें-> बिल्ड पथ -> कॉन्फ़िगर पथ का निर्माण करें ...-> स्रोत [टैब] -> फ़ोल्डर जोड़ें)।

यहां बताया गया है कि मेरी pomफ़ाइल कैसी दिखती है और जैसा कि देखा जा सकता है कि कोई wsdlLocation विकल्प नहीं है:

       <plugin>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-codegen-plugin</artifactId>
            <version>${cxf.version}</version>
            <executions>
                <execution>
                    <id>generate-sources</id>
                    <phase>generate-sources</phase>
                    <configuration>
                        <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
                        <wsdlOptions>
                            <wsdlOption>
                                <wsdl>classpath:wsdl/FOO_SERVICE.wsdl</wsdl>
                            </wsdlOption>
                        </wsdlOptions>
                    </configuration>
                    <goals>
                        <goal>wsdl2java</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

और यहाँ उत्पन्न सेवा है। जैसा कि देखा जा सकता है कि URL ClassLoader से प्राप्त किया गया है न कि निरपेक्ष फ़ाइल-पथ से

@WebServiceClient(name = "EventService", 
              wsdlLocation = "classpath:wsdl/FOO_SERVICE.wsdl",
              targetNamespace = "http://www.sas.com/xml/schema/sas-svcs/rtdm-1.1/wsdl/") 
public class EventService extends Service {

public final static URL WSDL_LOCATION;

public final static QName SERVICE = new QName("http://www.sas.com/xml/schema/sas-svcs/rtdm-1.1/wsdl/", "EventService");
public final static QName EventPort = new QName("http://www.sas.com/xml/schema/sas-svcs/rtdm-1.1/wsdl/", "EventPort");
static {
    URL url = EventService.class.getClassLoader().getResource("wsdl/FOO_SERVICE.wsdl");
    if (url == null) {
        java.util.logging.Logger.getLogger(EventService.class.getName())
            .log(java.util.logging.Level.INFO, 
                 "Can not initialize the default wsdl from {0}", "classpath:wsdl/FOO_SERVICE.wsdl");
    }       
    WSDL_LOCATION = url;   
}

<configuration> <sourceRoot>${basedir}/src/main/java/</sourceRoot> <wsdlRoot>${basedir}/src/main/resources/</wsdlRoot> <includes> <include>*.wsdl</include> </includes> </configuration> मैं सभी .wsdl फाइल को क्लास पाथ में शामिल करता हूं फिर मैं wsdl लोकेशन को कैसे निर्दिष्ट कर सकता हूं ताकि हर .java फाइल कॉन्टेन्स संबंधित .wsdl पाथ को बना सके। अग्रिम में धन्यवाद। @ आलसी
खालिद शाह

2

गंभीरता से, शीर्ष उत्तर मेरे लिए काम नहीं कर रहा है। कोशिश की cxf.version 2.4.1 और 3.0.10। और हर बार wsdlLocation के साथ पूर्ण पथ उत्पन्न करें।

मेरा समाधान wsdl2javaके apache-cxf-3.0.10\bin\ साथ कमांड का उपयोग करना है -wsdlLocation classpath:wsdl/QueryService.wsdl

विवरण:

    wsdl2java -encoding utf-8 -p com.jeiao.boss.testQueryService -impl -wsdlLocation classpath:wsdl/testQueryService.wsdl http://127.0.0.1:9999/platf/testQueryService?wsdl

0

@ मॉर्टिन डेविलर्स समाधान ठीक काम करता है। पूर्णता के लिए, नीचे दिए गए चरण प्रदान करें:

  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. यहाँ pom फाइल में फुल कोड जेनरेशन पार्ट है, जेनरेट कोड में धाराप्रवाह एपी के साथ।

    <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>

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