Masalahnya adalah saya perlu membangun klien layanan web dari file yang telah saya sediakan. Saya telah menyimpan file ini di sistem file lokal dan, sementara saya menyimpan file WSDL di folder sistem file yang benar, semuanya baik-baik saja. Ketika saya menyebarkannya ke server atau menghapus WSDL dari folder sistem file, proxy tidak dapat menemukan WSDL dan memunculkan kesalahan. Saya telah mencari di web dan saya menemukan posting berikut ini, namun saya tidak dapat membuatnya berfungsi:
JAX-WS Memuat WSDL dari jar
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
Saya menggunakan NetBeans 6.1 (ini adalah aplikasi warisan yang telah saya perbarui dengan klien layanan web baru ini). Di bawah ini adalah kelas proxy 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);
}
}
Ini kode saya untuk menggunakan proxy:
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 meletakkan salinan WSDL di web-inf / wsdl / client / SOAService , jadi saya tidak ingin menambahkannya ke META-INF juga. Kelas layanan berada di WEB-INF / class / com / ibm / eci / soaservice / dan variabel baseurl berisi jalur lengkap sistem file ke sana (c: \ path \ to \ the \ project ... \ soaservice). Kode di atas menimbulkan kesalahan:
javax.xml.ws.WebServiceException: Gagal mengakses WSDL di: file: /WEB-INF/wsdl/client/SOAService.wsdl. Itu gagal dengan: \ WEB-INF \ wsdl \ client \ SOAService.wsdl (tidak dapat menemukan jalur)
Jadi, pertama-tama, haruskah saya memperbarui lokasi wsd dari kelas proxy? Lalu bagaimana cara mengetahui class SOAService di WEB-INF / class / com / ibm / eci / soaservice untuk mencari WSDL di \ WEB-INF \ wsdl \ client \ SOAService.wsdl?
DIEDIT : Saya telah menemukan tautan lain ini - http://jianmingli.com/wp/?cat=41 , yang mengatakan untuk meletakkan WSDL ke jalur kelas. Saya malu bertanya: bagaimana cara memasukkannya ke classpath aplikasi web?
Jawaban:
Pilihan terbaik adalah menggunakan jax-ws-catalog.xml
Saat Anda mengkompilasi file WSDL lokal, timpa lokasi WSDL dan atur ke sesuatu seperti
Jangan khawatir ini hanya URI dan bukan URL, artinya Anda tidak harus memiliki WSDL yang tersedia di alamat itu.
Anda dapat melakukannya dengan meneruskan opsi wsdllocation ke kompiler wsdl ke java.
Melakukannya akan mengubah kode proxy Anda dari
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; }
untuk
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; }
File pemberitahuan: // diubah menjadi http: // di konstruktor URL.
Sekarang hadir dalam jax-ws-catalog.xml. Tanpa jax-ws-catalog.xml jax-ws memang akan mencoba memuat WSDL dari lokasi
dan gagal, karena WSDL tersebut tidak akan tersedia.Tetapi dengan jax-ws-catalog.xml Anda dapat mengarahkan jax-ws ke WSDL yang dikemas secara lokal setiap kali mencoba mengakses WSDL @
.Berikut 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>
Apa yang Anda lakukan adalah memberi tahu jax-ws bahwa kapan pun WSDL perlu dimuat
, itu harus memuatnya dari jalur lokal wsdl / SOAService.wsdl.Sekarang di mana Anda harus meletakkan wsdl / SOAService.wsdl dan jax-ws-catalog.xml? Itu pertanyaan jutaan dolar bukan?
Ini harus berada di direktori META-INF dari jar aplikasi Anda.
jadi seperti ini
Dengan cara ini Anda bahkan tidak perlu mengganti URL di klien Anda yang mengakses proxy. WSDL diambil dari dalam JAR Anda, dan Anda tidak perlu memiliki jalur sistem file yang di-hardcode dalam kode Anda.
Info lebih lanjut tentang jax-ws-catalog.xml http://jax-ws.java.net/nonav/2.1.2m1/docs/catalog-support.html
Semoga membantu
sumber
Satu pendekatan lain yang telah berhasil kami lakukan adalah menghasilkan kode proxy klien WS menggunakan wsimport (dari Ant, sebagai tugas Ant) dan menentukan atribut wsdlLocation.
<wsimport debug="true" keep="true" verbose="false" target="2.1" sourcedestdir="${generated.client}" wsdl="${src}${wsdl.file}" wsdlLocation="${wsdl.file}"> </wsimport>
Karena kita menjalankan ini untuk sebuah proyek dengan beberapa WSDL, skrip menyelesaikan nilai $ (wsdl.file} secara dinamis yang diatur menjadi /META-INF/wsdl/YourWebServiceName.wsdl relatif terhadap lokasi JavaSource (atau / src, tergantung bagaimana Anda menyiapkan proyek). Selama proses pembuatan, file WSDL dan XSD disalin ke lokasi ini dan dikemas dalam file JAR. (mirip dengan solusi yang dijelaskan oleh Bhasakar di atas)
Catatan: pastikan file WSDL menggunakan referensi relatif ke XSD yang diimpor dan bukan URL http:
<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>
Dalam kode yang dihasilkan , kami menemukan ini:
/** * 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; } }
Mungkin ini bisa membantu juga. Ini hanya pendekatan berbeda yang tidak menggunakan pendekatan "katalog".
sumber
Terima kasih banyak atas jawaban Bhaskar Karambelkar yang menjelaskan secara rinci dan memperbaiki masalah saya. Tetapi saya juga ingin menyampaikan kembali jawabannya dalam tiga langkah sederhana untuk seseorang yang sedang terburu-buru untuk memperbaikinya
wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
Buat file xml jax-ws-catalog.xml di bawah META-INF seperti di bawah ini
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system"> <system systemId="http://localhost/wsdl/yourwsdlname.wsdl" uri="wsdl/yourwsdlname.wsdl" /> </catalog>
Sekarang kemas toples Anda. Tidak ada lagi referensi ke direktori lokal, semuanya dikemas dan direferensikan di dalamnya
sumber
Bagi mereka yang masih mencari solusi di sini, solusi termudah adalah menggunakan
<wsdlLocation>
, tanpa mengubah kode apa pun. Langkah kerja diberikan di bawah ini:src/main/resource
Di file pom, tambahkan wsdlDirectory dan wsdlLocation (jangan lewatkan / di awal wsdlLocation), seperti di bawah ini. Sementara wsdlDirectory digunakan untuk menghasilkan kode dan wsdlLocation digunakan saat runtime untuk membuat proxy dinamis.
Kemudian di kode java Anda (dengan konstruktor no-arg):
MyPort myPort = new MyPortService().getMyPort();
Untuk kelengkapan, saya menyediakan di sini bagian pembuatan kode lengkap, dengan api yang lancar dalam kode yang dihasilkan.
<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>
sumber
Bagi Anda yang menggunakan Spring, Anda cukup mereferensikan classpath-resource menggunakan classpath-protocol. Jadi dalam kasus wsdlLocation, ini menjadi:
Perhatikan bahwa itu bukan perilaku Java standar. Lihat juga: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html
sumber
Memiliki masalah yang sama persis dengan yang dijelaskan di sini. Tidak peduli apa yang saya lakukan, mengikuti contoh di atas, untuk mengubah lokasi file WSDL saya (dalam kasus kami dari server web), itu masih merujuk ke lokasi asli yang tertanam dalam pohon sumber proses server.
Setelah BANYAK jam mencoba men-debug ini, saya perhatikan bahwa Pengecualian selalu dilemparkan dari baris yang sama persis (dalam kasus saya 41). Akhirnya pagi ini, saya memutuskan untuk mengirim kode klien sumber saya ke mitra dagang kami sehingga mereka setidaknya dapat memahami bagaimana kodenya terlihat, tetapi mungkin membuatnya sendiri. Yang membuat saya terkejut dan ngeri, saya menemukan banyak file kelas bercampur dengan file .java saya dalam pohon sumber klien saya. Aneh sekali !! Saya menduga ini adalah produk sampingan dari alat pembuat klien JAX-WS.
Setelah saya menghapus file .class konyol itu dan melakukan pembersihan dan rekondisi kode klien sepenuhnya, semuanya bekerja dengan sempurna !! Tidak masuk akal !!
YMMV, Andrew
sumber