development

JAX-WS 클라이언트 : 로컬 WSDL에 액세스하기위한 올바른 경로는 무엇입니까?

big-blog 2020. 10. 5. 08:18
반응형

JAX-WS 클라이언트 : 로컬 WSDL에 액세스하기위한 올바른 경로는 무엇입니까?


문제는 제공된 파일에서 웹 서비스 클라이언트를 빌드해야한다는 것입니다. 이 파일을 로컬 파일 시스템에 저장했으며 WSDL 파일을 올바른 파일 시스템 폴더에 보관하지만 모든 것이 정상입니다. 서버에 배포하거나 파일 시스템 폴더에서 WSDL을 제거하면 프록시가 WSDL을 찾을 수없고 오류가 발생합니다. 웹을 검색했는데 다음 게시물을 찾았지만 아직 작동하지 않았습니다.
JAX-WS jar에서 WSDL로드
http://www.java.net/forum/topic/glassfish/metro -and-jaxb / client-jar-cant-find-local-wsdl-0
http://blog.vinodsingh.com/2008/12/locally-packaged-wsdl.html

NetBeans 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는 WSDL의 복사본을 web-inf / wsdl / client / SOAService 에 저장하므로 META-INF 에도 추가하고 싶지 않습니다 . 서비스 클래스는 WEB-INF / classes / com / ibm / eci / soaservice /에 있으며 baseurl 변수에는 파일 시스템 전체 경로가 포함됩니다 (c : \ path \ to \ the \ project ... \ soaservice). 위의 코드는 오류를 발생시킵니다.

javax.xml.ws.WebServiceException : file : /WEB-INF/wsdl/client/SOAService.wsdl에서 WSDL에 액세스하지 못했습니다. 실패했습니다 : \ WEB-INF \ wsdl \ client \ SOAService.wsdl (경로를 찾을 수 없음)

그래서 우선 프록시 클래스의 wsdllocation을 업데이트해야합니까? 그렇다면 WEB-INF / classes / com / ibm / eci / soaservice의 SOAService 클래스에 \ WEB-INF \ wsdl \ client \ SOAService.wsdl에서 WSDL을 검색하도록 어떻게 지시합니까?

편집 됨 : -이 다른 링크를 발견했습니다 http://jianmingli.com/wp/?cat=41 , 클래스 패스에 WSDL을 넣어 말한다. 부끄럽습니다. 웹 애플리케이션 클래스 경로에 어떻게 넣습니까?


가장 좋은 방법은 jax-ws-catalog.xml을 사용하는 것입니다.

로컬 WSDL 파일을 컴파일 할 때 WSDL 위치를 재정의하고 다음과 같이 설정합니다.

http : //localhost/wsdl/SOAService.wsdl

URL이 아닌 URI 일 뿐이므로 해당 주소에서 WSDL을 사용할 필요가 없습니다.
wsdllocation 옵션을 wsdl to java 컴파일러에 전달하여이를 수행 할 수 있습니다.

이렇게하면 프록시 코드가

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 생성자에서 file : //이 http : //로 변경되었습니다.

이제 jax-ws-catalog.xml로 제공됩니다. jax-ws-catalog.xml이 없으면 jax-ws는 실제로 해당 위치에서 WSDL을로드하려고합니다.

http : //localhost/wsdl/SOAService.wsdl
그러한 WSDL을 사용할 수 없으므로 실패합니다.

그러나 jax-ws-catalog.xml을 사용하면 WSDL @에 액세스하려고 할 때마다 jax-ws를 로컬 패키지 WSDL로 리디렉션 할 수 있습니다.

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-catalog.xml을 어디에 넣어야합니까? 그게 백만 달러짜리 질문이지 않나요?
애플리케이션 jar의 META-INF 디렉토리에 있어야합니다.

그래서 이렇게

ABCD.jar  
| __ META-INF    
    | __ jax-ws-catalog.xml  
    | __ wsdl  
        | __ SOAService.wsdl  

이렇게하면 프록시에 액세스하는 클라이언트의 URL을 재정의하지 않아도됩니다. WSDL은 JAR 내에서 선택되므로 코드에 하드 코딩 된 파일 시스템 경로가 필요하지 않습니다.

jax-ws-catalog.xml에 대한 추가 정보 http://jax-ws.java.net/nonav/2.1.2m1/docs/catalog-support.html

도움이되는 희망


우리가 성공적으로 취한 또 다른 접근 방식은 wsimport (Ant 태스크로 Ant에서)를 사용하여 WS 클라이언트 프록시 코드를 생성하고 wsdlLocation 속성을 지정하는 것입니다.

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

Since we run this for a project w/ multiple WSDLs, the script resolves the $(wsdl.file} value dynamically which is set up to be /META-INF/wsdl/YourWebServiceName.wsdl relative to the JavaSource location (or /src, depending on how you have your project set up). During the build proess, the WSDL and XSDs files are copied to this location and packaged in the JAR file. (similar to the solution described by Bhasakar above)

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

Note: make sure the WSDL files are using relative refrerences to any imported XSDs and not http URLs:

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

In the generated code, we find this:

/**
 * 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;
    }

}

Perhaps this might help too. It's just a different approach that does not use the "catalog" approach.


Thanks a ton for Bhaskar Karambelkar's answer which explains in detail and fixed my issue. But also I would like to re phrase the answer in three simple steps for someone who is in a hurry to fix

  1. Make your wsdl local location reference as wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
  2. Create a META-INF folder right under the src. Put your wsdl file/s in a folder under META-INF, say META-INF/wsdl
  3. Create an xml file jax-ws-catalog.xml under META-INF as below

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

Now package your jar. No more reference to the local directory, it's all packaged and referenced within


For those of you using Spring, you can simply reference any classpath-resource using the classpath-protocol. So in case of the wsdlLocation, this becomes:

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

Note that is not standard Java behavior. See also: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html


Had the exact same problem that is described herein. No matter what I did, following the above examples, to change the location of my WSDL file (in our case from a web server), it was still referencing the original location embedded within the source tree of the server process.

After MANY hours trying to debug this, I noticed that the Exception was always being thrown from the exact same line (in my case 41). Finally this morning, I decided to just send my source client code to our trade partner so they can at least understand how the code looks, but perhaps build their own. To my shock and horror I found a bunch of class files mixed in with my .java files within my client source tree. How bizarre!! I suspect these were a byproduct of the JAX-WS client builder tool.

Once I zapped those silly .class files and performed a complete clean and rebuild of the client code, everything works perfectly!! Redonculous!!

YMMV, Andrew

참고URL : https://stackoverflow.com/questions/4163586/jax-ws-client-whats-the-correct-path-to-access-the-local-wsdl

반응형