JAX-WS istemcisi: yerel WSDL'ye erişmenin doğru yolu nedir?


86

Sorun şu ki, bana verilen bir dosyadan bir web hizmeti istemcisi oluşturmam gerekiyor. Bu dosyayı yerel dosya sisteminde sakladım ve WSDL dosyasını doğru dosya sistemi klasöründe tutarken her şey yolunda. Bir sunucuya dağıttığımda veya WSDL'yi dosya sistemi klasöründen kaldırdığımda proxy WSDL'yi bulamıyor ve bir hata veriyor. Web'de arama yaptım ve aşağıdaki gönderileri buldum, henüz çalışmasını sağlayamadım:
JAX-WS WSDL'yi jar
http://www.java.net/forum/topic/glassfish/metro'dan yükleme -and-jaxb / client-jar-cant-find-local-wsdl-0
http://blog.vinodsingh.com/2008/12/locally-packaged-wsdl.html

NetBeans 6.1 kullanıyorum (bu, bu yeni web hizmeti istemcisiyle güncellemem gereken eski bir uygulamadır). JAX-WS proxy sınıfı aşağıdadır:

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

}


Proxy kullanmak için benim kodum:

   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'nin bir kopyasını web-inf / wsdl / client / SOAService içine koydu , bu yüzden META- INF'e de eklemek istemiyorum . Hizmet sınıfları WEB-INF / classes / com / ibm / eci / soaservice / içindedir ve baseurl değişkeni, dosya sisteminin tam yolunu içerir (c: \ yol \ - \ proje ... \ soaservice). Yukarıdaki kod hatayı ortaya çıkarır:

javax.xml.ws.WebServiceException: WSDL'ye şu adresten erişilemedi: dosya: /WEB-INF/wsdl/client/SOAService.wsdl. Şununla başarısız oldu: \ WEB-INF \ wsdl \ client \ SOAService.wsdl (yolu bulamıyor)

Öyleyse, öncelikle proxy sınıfının wsdllocation'unu güncellemeli miyim? O halde WEB-INF / classes / com / ibm / eci / soaservice'deki SOAService sınıfına \ WEB-INF \ wsdl \ client \ SOAService.wsdl'de WSDL'yi aramasını nasıl söyleyebilirim?

DÜZENLENMİŞ : Bu diğer bağlantıyı buldum - http://jianmingli.com/wp/?cat=41 , WSDL'yi sınıf yoluna koymayı söylüyor. Sormaya utanıyorum: bunu web uygulaması sınıf yoluna nasıl koyarım?


Benzer soru: JAX-WS
WSDL'yi

Yanıtlar:


117

En iyi seçenek jax-ws-catalog.xml kullanmaktır.

Yerel WSDL dosyasını derlediğinizde, WSDL konumunu geçersiz kılın ve aşağıdaki gibi bir şeye ayarlayın:

http: //localhost/wsdl/SOAService.wsdl

Endişelenmeyin, bu yalnızca bir URI'dir ve bir URL değildir, yani o adreste WSDL'ye sahip olmanız gerekmez.
Bunu, wsdllocation seçeneğini wsdl'ye java derleyicisine geçirerek yapabilirsiniz.

Bunu yapmak, proxy kodunuzu

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

-e

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

Notice file: //, URL yapıcısında http: // olarak değiştirildi.

Şimdi jax-ws-catalog.xml'de geliyor. Jax-ws-catalog.xml olmadan jax-ws, WSDL'yi konumdan gerçekten yüklemeye çalışır.

http: //localhost/wsdl/SOAService.wsdl
ve böyle bir WSDL mevcut olmayacağından başarısız olur.

Ancak jax-ws-catalog.xml ile jax-ws'yi WSDL @ 'ye her erişmeye çalıştığında yerel olarak paketlenmiş bir WSDL'ye yeniden yönlendirebilirsiniz.

http: //localhost/wsdl/SOAService.wsdl
.

İşte 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'ye ne zaman WSDL yüklemesi gerektiğini söylüyorsunuz.

http: //localhost/wsdl/SOAService.wsdl
, onu wsdl / SOAService.wsdl yerel yolundan yüklemelidir.

Şimdi wsdl / SOAService.wsdl ve jax-ws-catalog.xml'yi nereye koymalısınız? Milyon dolarlık soru bu değil mi?
Uygulama jar'ınızın META-INF dizininde olmalıdır.

yani bunun gibi bir şey

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

Bu şekilde, istemcinizde proxy'ye erişen URL'yi geçersiz kılmanız bile gerekmez. WSDL, JAR'ınızın içinden alınır ve kodunuzda sabit kodlanmış dosya sistemi yollarına sahip olmak zorunda kalmazsınız.

Jax-ws-catalog.xml hakkında daha fazla bilgi http://jax-ws.java.net/nonav/2.1.2m1/docs/catalog-support.html

umarım yardımcı olur


Tamam, sorunu web uygulamasında bu şekilde çözemiyorum: wsdl'yi web-inf'in içine koymaya çalıştım, muhtemelen bilgi eksikliğimden dolayı başarılı olamadım. Her neyse, bir kavanozla çalışıyor, bu yüzden baştan yapılması gerektiği gibi bir sarmalayıcı kitaplığı yapacağım. Desteğiniz için teşekkür ederiz

Bu cevabı başarılı bir şekilde kullanabildim ve bunun, diğer makaleler ve eğitimlerin belgelediği diğer tüm alternatiflerden daha iyi bir çözüm olduğuna inanıyorum. Bu yüzden benim için bu en iyi uygulamadır. Sadece bu çözümün JAX-WS konusunu kapsayan diğer resmi makalelerde ve eğitimlerde neden belgelenmediğini merak ediyorum.
Rahul Khimasia

19

Başarılı bir şekilde uyguladığımız diğer bir yaklaşım, wsimport kullanarak (Ant'tan bir Ant görevi olarak) WS istemci proxy kodunu oluşturmak ve wsdlLocation özniteliğini belirlemektir.

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

Bunu birden çok WSDL'li bir proje için çalıştırdığımız için, komut dosyası, JavaSource konumuna göre (veya / src, Projenizi nasıl kurduğunuza bağlı olarak). Oluşturma işlemi sırasında, WSDL ve XSD dosyaları bu konuma kopyalanır ve JAR dosyasında paketlenir (yukarıda Bhasakar tarafından açıklanan çözüme benzer)

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

Not: WSDL dosyalarının http URL'leri değil, içe aktarılan XSD'ler için göreli referanslar kullandığından emin olun:

  <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 oluşturulan kod, bunu buluyoruz:

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

}

Belki bu da yardımcı olabilir. Bu sadece "katalog" yaklaşımını kullanmayan farklı bir yaklaşımdır.


Bu yaklaşımı beğendim ... ama neden META-INF dizini?
IcedDante

1
Lütfen bunun için JDK 6 ile varsayılan olarak gelen 2.1'in değil JAX-WS RI
2.2'nin

4

Bhaskar Karambelkar'ın sorunumu ayrıntılı olarak açıklayan ve düzelten cevabı için çok teşekkürler. Ancak, düzeltmek için acelesi olan biri için yanıtı üç basit adımda yeniden ifade etmek istiyorum.

  1. Wsdl yerel konum referansınızı şu şekilde yapın: wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
  2. Src'nin hemen altında bir META-INF klasörü oluşturun. Wsdl dosyalarınızı META-INF altındaki bir klasöre koyun, örneğin META-INF / wsdl
  3. META-INF altında aşağıdaki gibi bir xml dosyası jax-ws-catalog.xml oluşturun

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

Şimdi kavanozunuzu paketleyin. Yerel dizine artık referans yok, hepsi paketlenmiş ve içinde referans gösteriliyor


4

Buraya hala çözüm için gelenler için en kolay çözüm <wsdlLocation>herhangi bir kodu değiştirmeden kullanmak olacaktır . Çalışma adımları aşağıda verilmiştir:

  1. Wsdl'nizi aşağıdaki gibi kaynak dizinine koyun: src/main/resource
  2. Pom dosyasında, aşağıdaki gibi hem wsdlDirectory hem de wsdlLocation ekleyin (wsdlLocation'ın başlangıcında / kaçırmayın). WsdlDirectory kod üretmek için kullanılırken, wsdlLocation çalışma zamanında dinamik proxy oluşturmak için kullanılır.

    <wsdlDirectory>src/main/resources/mydir</wsdlDirectory>
    <wsdlLocation>/mydir/my.wsdl</wsdlLocation>
    
  3. Sonra java kodunuzda (argansız yapıcısıyla):

    MyPort myPort = new MyPortService().getMyPort();
    
  4. Tamlık için, burada üretilen kodda akıcı api ile tam kod üretme kısmı sağlıyorum.

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



0

Vardı tam tarifnamede anlatılan aynı problem. WSDL dosyamın konumunu değiştirmek için yukarıdaki örnekleri izleyerek ne yaparsam yapayım (bizim durumumuzda bir web sunucusundan), yine de sunucu işleminin kaynak ağacına gömülü orijinal konumu referans veriyordu.

Birçok saatin bu hatayı gidermeye çalıştıktan sonra, İstisnanın her zaman aynı satırdan atıldığını fark ettim (benim durumumda 41). Sonunda bu sabah, kaynak müşteri kodumu ticaret ortağımıza göndermeye karar verdim, böylece en azından kodun nasıl göründüğünü anlayabilirler, ama belki de kendi kodlarını oluşturabilirler. Benim için şok ve dehşet Müvekkilim kaynak ağacındaki benim .java dosyaları ile karışık sınıf dosyaları bir demet bulundu. Ne kadar tuhaf !! Bunların JAX-WS istemci oluşturucu aracının bir yan ürünü olduğundan şüpheleniyorum.

Bu aptal .class dosyalarını zapladıktan ve istemci kodunu tamamen temizleyip yeniden oluşturduğumda, her şey mükemmel çalışıyor !! Redonculous !!

YMMV, Andrew

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.