programing

CXF 또는 JAX-WS에서 생성된 웹 서비스 클라이언트에서 WSDL 위치를 지정할 필요가 없도록 하려면 어떻게 해야 합니까?

randomtip 2022. 8. 30. 21:53
반응형

CXF 또는 JAX-WS에서 생성된 웹 서비스 클라이언트에서 WSDL 위치를 지정할 필요가 없도록 하려면 어떻게 해야 합니까?

maven을 통해 CXF에서 wsdl2java를 사용하여 웹 서비스 클라이언트를 생성하면(wsimport와 유사한 것이 생성됩니다), 서비스는 다음과 같은 코드로 시작됩니다.

@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 파일(및 WSDL이 Import하는 모든 파일, 기타 WSDL 및 XSD)을 jar 파일 어딘가에 저장하고 클래스 패스를 하는 것입니다.하지만 우리는 이것을 피하고 싶다.WSDL과 XSD를 기반으로 한 CXF와 JAXB에 의해 모두 생성되었기 때문에 실행 시 WSDL을 알 필요가 없습니다.

로케이션을 으로 하며( 이것은 입니다), ""wsdlLocation" "WSDL " " " " " " " " " 입니다.에 maven을 하려고 했습니다.<wsdlLocation></wsdlLocation>wsdl Location sdsdsdsd 。 있기 될 뿐입니다.는 정말 추악한을 했다.<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. 모든 클래스가 CXF 및 JAXB에 의해 생성된 경우에도 WSDL 로케이션이 필요한가요?그렇다면 왜?

  2. WSDL 로케이션이 실제로 필요하지 않은 경우 CXF가 WSDL 로케이션을 생성하지 않고 완전히 회피할 수 있는 적절하고 깨끗한 방법은 무엇일까요?

  3. 그 해킹으로 어떤 부작용을 얻을 수 있을까요?아직 어떤 일이 일어나는지 테스트 할 수 없기 때문에, 누군가가 미리 말해 주었으면 합니다.

나는 오늘 드디어 이 질문에 대한 정답을 알아냈다.

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

「 」의 있는 .wsdlLocationclasspath:그러면 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;
    }

이것은 cxf-codegen-plugin 버전 2.4.1 이후에서만 동작합니다.

사용하고 있습니다

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

즉, 클래스 패스에 상대적인 경로를 사용합니다.

WSDL은 실행 시 marshal/unmarshal 메시지 검증을 위해 필요할 수 있습니다.

하시는 분org.jvnet.jax-ws-commons:jaxws-maven-plugin빌드 시 WSDL에서 클라이언트를 생성하려면 다음 절차를 수행합니다.

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

1) 경우에 따라 그렇습니다.WSDL에 Policies 등의 실행 시 동작을 지시하는 것이 포함되어 있는 경우 실행 시 WSDL이 필요할 수 있습니다.정책 관련 사항 등에 대해서는 아티팩트가 생성되지 않습니다.또, 일부 불명확한 RPC/Literal의 경우, 필요한 네임스페이스가 모두 생성된 코드(스펙별)로 출력되는 것은 아닙니다).따라서 wsdl이 필요합니다.잘 알려지지 않은 사건들이지만.

2) 이런 게 통할 줄 알았어요.CXF의 어떤 버전입니까?벌레 같은데?빈 문자열(스페이스만)을 사용할 수 있습니다.그게 먹힐지 안 먹힐지 모르겠어.즉, 코드에서는 WSDL URL을 사용하는 컨스트럭터를 사용하여 null을 전달할 수 있습니다.wsdl은 사용되지 않습니다.

3) 위의 제한 사항만.

나는 이 모든 것을

static {
    WSDL_LOCATION = null;
}

wsdlurl에 null을 지정하도록 pom 파일을 설정합니다.

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

CXF 3.1.7 업데이트

을 WSDL에 .src/main/resourcesEclipse -> 추가. -> 출처 [-> 추가.- > [ ] - > [ ] - > [ ]

제 방법은 이렇습니다.pom, NO, NO가 .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;   
}

wsdl2java 사용을 피할 수 있습니까?CXF FrontEnd API를 사용하여 SOAP Webservice를 바로 호출할 수 있습니다.유일한 장점은 클라이언트 측에서 SEI와 VO를 작성해야 한다는 것입니다.여기 샘플 코드가 있습니다.

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/

정말이지, 맨 위의 답은 나에게 효과가 없다. cxf를 시도했다.버전 2.4.1 및 3.0.10. 및 wsdlLocation을 사용하여 절대 경로를 매번 생성합니다.

의 은 ★★★★★★★★★★★★★★★★★★를 사용하는 것입니다.wsdl2javaapache-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

@Martin Devillers 솔루션은 정상적으로 동작합니다.완성도를 높이기 위해 다음 단계를 제공합니다.

  1. 을 : wsdl の 음 like like like like like like src/main/resource
  2. pom 파일에서 다음과 같이 wsdlDirectory와 wsdlLocation을 모두 추가합니다(wsdlLocation의 선두에 /를 놓치지 마십시오).wsdlDirectory는 코드 생성에 사용되며 wsdlLocation은 실행 시 동적 프록시를 생성하기 위해 사용됩니다.

    <wsdlDirectory>src/main/resources/mydir</wsdlDirectory>
    <wsdlLocation>/mydir/my.wsdl</wsdlLocation>
    
  3. 그런 다음 Java 코드(no-arg 컨스트럭터 포함):

    MyPort myPort = new MyPortService().getMyPort();
    
  4. 생성된 코드에 fluent api를 가진 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>
    

나는 자동 생성으로 생산될 수 있었다.

    static {
        WSDL_LOCATION = null;
    }

와 함께

    <wsdlLocation>null</wsdlLocation>

하지만 이 일의 목적은 한정되어 있는 것 같습니다.WS 클라이언트의 초기화를 최소한으로 억제하고 가능한 한 단기간에 실현하려고 했습니다.svc = new MyService(); binding = svc.getMySoapPort();하지만 이제 알았다.

INFO: Creating Service {http://www.example.com/MyApi}MyApiService from class com.company.MyApiPortType

대신

INFO: Creating Service {http://www.example.com/MyApi}MyApiService from WSDL ...

그런 것 같아요.new MyService();어쨌든 비용이 많이 들기 때문에, 나는 그것의 오랜 동시 사용 예를 다시 생각해야 한다...따라서 WSDL의 런타임 해석은 문제가 되지 않습니다.

언급URL : https://stackoverflow.com/questions/4455195/how-to-avoid-the-need-to-specify-the-wsdl-location-in-a-cxf-or-jax-ws-generated

반응형