Jak uniknąć konieczności określania lokalizacji WSDL w kliencie WebService generowanym przez CXF lub JAX-WS?

Kiedy generuję klienta webservice za pomocą wsdl2java z CXF (który generuje coś podobnego do wsimport), przez maven, moje usługi zaczynają się od takich kodów:

@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;
    }

Zakodowana ścieżka absolutna jest naprawdę do bani. Wygenerowana klasa nie będzie działać na żadnym innym komputerze poza moim.

Pierwszym pomysłem jest umieszczenie pliku WSDL (plus wszystko, co importuje, inne WSDL i XSD) gdzieś w pliku jar i classpath go. Ale chcemy tego uniknąć. Od kiedy to wszystko było generowane przez CXF i JAXB oparte na WSDLs i XSDs, nie widzimy sensu w potrzebie znać WSDL w czasie wykonywania.

Atrybut wsdlLocation ma na celu nadpisanie lokalizacji WSDL( przynajmniej to czytałem gdzieś), a domyślną wartością jest"". Ponieważ używamy Mavena, staraliśmy się umieścić <wsdlLocation></wsdlLocation> wewnątrz konfiguracji CXF, aby zmusić generator źródłowy do pozostawienia pustej lokalizacji wsdlLocation. Jednak to po prostu sprawia, że ignoruje znacznik XML, ponieważ jest pusty. Zrobiliśmy naprawdę brzydki haniebny hack, za pomocą <wsdlLocation>" + "</wsdlLocation>.

To zmienia również inne miejsca:

@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;
    }
Więc moje pytania to:
  1. Czy naprawdę potrzebujemy lokalizacji WSDL, nawet jeśli wszystkie klasy były generowane przez CXF i JAXB? Jeśli tak, to dlaczego?

  2. Jeśli tak naprawdę nie potrzebujemy lokalizacji WSDL, jaki jest właściwy i czysty sposób, aby CXF go nie generował i całkowicie go unikał?

  3. Jakie złe skutki uboczne możemy uzyskać z tego hack? Nadal nie możemy przetestować żeby zobaczyć, co się stanie, więc gdyby ktoś mógł powiedzieć z góry, byłoby miło.

Author: Donal Fellows, 2010-12-16

8 answers

W końcu znalazłem właściwą odpowiedź na to pytanie dzisiaj.

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

Zauważ, że dodałem prefiks w wsdlLocation do classpath:. To mówi wtyczce, że wsdl będzie na classpath zamiast ścieżki bezwzględnej. Następnie wygeneruje kod podobny do tego:

@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;
    }

Zauważ, że działa to tylko z wersją 2.4.1 lub nowszą wtyczki CXF-codegen-plugin.

 186
Author: Kyle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-12 11:54:41

Używamy

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

Innymi słowy, użyj ścieżki względem ścieżki classpath.

Uważam, że WSDL może być potrzebne w czasie wykonywania do walidacji wiadomości podczas marshal/unmarshal.

 19
Author: BPS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-13 16:05:49

1) w niektórych przypadkach tak. Jeśli WSDL zawiera takie zasady i takie, które kierują zachowaniem runtime, to WSDL może być wymagane w czasie runtime. Artefakty nie są generowane dla rzeczy związanych z Polityką itp. Ponadto, w niektórych niejasnych przypadkach RPC / dosłownych, nie wszystkie przestrzenie nazw, które są potrzebne, są wyprowadzane w wygenerowanym kodzie (według specyfikacji). Dlatego wsdl byłby im potrzebny. Niejasne przypadki.

2) myślałem, że coś takiego zadziała. Jaka wersja CXF? Że brzmi jak robak. Możesz spróbować pusty łańcuch tam (tylko spacje). Nie wiem, czy to działa. To powiedziawszy, w kodzie możesz użyć konstruktora, który pobiera adres URL WSDL i po prostu przekazuje null. Wsdl nie zostałaby użyta.

3) Tylko powyższe ograniczenia.

 9
Author: Daniel Kulp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-15 22:03:14

Dla tych, którzy używają org.jvnet.jax-ws-commons:jaxws-maven-plugin do generowania klienta z WSDL w czasie kompilacji:

  • umieść WSDL gdzieś w swoim src/main/resources
  • Do Nie przedrostek wsdlLocation z classpath:
  • przedrostek wsdlLocation z /

Przykład:

  • WSDL jest przechowywany w /src/main/resources/foo/bar.wsdl
  • Konfiguracja jaxws-maven-plugin z <wsdlDirectory>${basedir}/src/main/resources/foo</wsdlDirectory> i <wsdlLocation>/foo/bar.wsdl</wsdlLocation>
 9
Author: Martin Devillers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-10 11:14:14

Czy jest możliwe, że możesz uniknąć używania wsdl2java? Możesz od razu użyć interfejsów API interfejsu CXF do wywołania usługi internetowej SOAP. Jedynym haczykiem jest to, że musisz stworzyć swój SEI i VOs na swoim kliencie. Oto przykładowy kod.

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());

    }
}

Możesz zobaczyć cały tutorial tutaj http://weblog4j.com/2012/05/01/developing-soap-web-service-using-apache-cxf/

 4
Author: Niraj Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-29 04:49:31

Udało mi się wygenerować

static {
    WSDL_LOCATION = null;
}

Poprzez skonfigurowanie pliku pom, aby miał null dla 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>
 4
Author: raisercostin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 22:05:29

Aktualizacja dla CXF 3.1.7

W moim przypadku umieściłem pliki WSDL w src/main/resources i dodałem tę ścieżkę do moich Strouces w Eclipse (kliknij prawym przyciskiem myszy na Project -> Build Path - > Configure Build Path...- >Source[Tab] - > Add Folder).

Oto jak wygląda mój plik pom i jak widać nie ma wsdlLocation opcja potrzebna:

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

A oto wygenerowana usługa. Jak widać adres URL jest pobierany z Classloadera, a nie z bezwzględnej ścieżki pliku

@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;   
}
 4
Author: Mazy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 22:06:20

/ Align = "center" bgcolor = "# e0ffe0 " / cesarz chin / / align = center / próbowałem cxf.Wersja 2.4.1 i 3.0.10. i generuj ścieżkę bezwzględną z wsdlLocation za każdym razem.

Moim rozwiązaniem jest użycie polecenia wsdl2java w apache-cxf-3.0.10\bin\ z -wsdlLocation classpath:wsdl/QueryService.wsdl.

Szczegóły:

    wsdl2java -encoding utf-8 -p com.jeiao.boss.testQueryService -impl -wsdlLocation classpath:wsdl/testQueryService.wsdl http://127.0.0.1:9999/platf/testQueryService?wsdl
 2
Author: jeiao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 22:07:48