Problem polega na tym, że muszę zbudować klienta usługi sieciowej na podstawie otrzymanego pliku. Zapisałem ten plik w lokalnym systemie plików i chociaż trzymam plik WSDL w odpowiednim folderze systemu plików, wszystko jest w porządku. Kiedy wdrażam go na serwerze lub usuwam WSDL z folderu systemu plików, proxy nie może znaleźć pliku WSDL i generuje błąd. Przeszukałem sieć i znalazłem następujące posty, ale nie udało mi się to zrobić:
JAX-WS Ładowanie WSDL z 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
Używam NetBeans 6.1 (jest to starsza aplikacja, którą muszę zaktualizować za pomocą tego nowego klienta usługi sieciowej). Poniżej znajduje się klasa 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);
}
}
Oto mój kod do korzystania z serwera 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 umieścił kopię WSDL w web-inf / wsdl / client / SOAService , więc nie chcę też dodawać jej do META-INF . Klasy usług znajdują się w WEB-INF / classes / com / ibm / eci / soaservice /, a zmienna baseurl zawiera pełną ścieżkę do systemu plików (c: \ path \ to \ the \ project ... \ soaservice). Powyższy kod wywołuje błąd:
javax.xml.ws.WebServiceException: nie można uzyskać dostępu do WSDL pod adresem: plik: /WEB-INF/wsdl/client/SOAService.wsdl. Błąd: \ WEB-INF \ wsdl \ client \ SOAService.wsdl (nie można znaleźć ścieżki)
Więc przede wszystkim, czy powinienem zaktualizować wsdllocation klasy proxy? Jak więc powiedzieć klasie SOAService w WEB-INF / classes / com / ibm / eci / soaservice, aby wyszukała WSDL w \ WEB-INF \ wsdl \ client \ SOAService.wsdl?
EDITED : Znalazłem ten inny link - http://jianmingli.com/wp/?cat=41 , który mówi, że należy umieścić WSDL w ścieżce klas. Wstydzę się zapytać: jak umieścić to w ścieżce klas aplikacji internetowej?
Odpowiedzi:
Najlepszą opcją jest użycie jax-ws-catalog.xml
Kiedy kompilujesz lokalny plik WSDL, zastąp lokalizację WSDL i ustaw ją na coś podobnego
Nie martw się, to jest tylko identyfikator URI, a nie adres URL, co oznacza, że nie musisz mieć dostępnego WSDL pod tym adresem.
Możesz to zrobić, przekazując opcję wsdllocation do wsdl do kompilatora java.
Spowoduje to zmianę kodu proxy z
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; }
do
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; }
Plik z powiadomieniami: // zmieniono na http: // w konstruktorze adresu URL.
Teraz jest w jax-ws-catalog.xml. Bez jax-ws-catalog.xml jax-ws rzeczywiście spróbuje załadować WSDL z tej lokalizacji
i zakończy się niepowodzeniem, ponieważ żaden taki WSDL nie będzie dostępny.Ale dzięki jax-ws-catalog.xml możesz przekierować jax-ws do lokalnie spakowanego WSDL, gdy próbuje uzyskać dostęp do WSDL @
.Oto 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>
To, co robisz, to mówienie jax-ws, że kiedykolwiek będzie musiał załadować WSDL z
, powinien załadować go ze ścieżki lokalnej wsdl / SOAService.wsdl.Teraz gdzie należy umieścić wsdl / SOAService.wsdl i jax-ws-catalog.xml? To jest pytanie za milion dolarów, prawda?
Powinien znajdować się w katalogu META-INF pliku jar aplikacji.
więc coś takiego
W ten sposób nie musisz nawet zastępować adresu URL w swoim kliencie, który uzyskuje dostęp do serwera proxy. WSDL jest pobierany z twojego JAR, a Ty unikasz konieczności umieszczania w kodzie na stałe zakodowanych ścieżek systemu plików.
Więcej informacji na temat jax-ws-catalog.xml http://jax-ws.java.net/nonav/2.1.2m1/docs/catalog-support.html
Mam nadzieję, że to pomoże
źródło
Innym podejściem, które z powodzeniem przyjęliśmy, jest wygenerowanie kodu proxy klienta WS przy użyciu narzędzia wsimport (z Ant, jako zadanie Ant) i określenie atrybutu wsdlLocation.
<wsimport debug="true" keep="true" verbose="false" target="2.1" sourcedestdir="${generated.client}" wsdl="${src}${wsdl.file}" wsdlLocation="${wsdl.file}"> </wsimport>
Ponieważ uruchamiamy to dla projektu z wieloma plikami WSDL, skrypt rozwiązuje wartość $ (wsdl.file} dynamicznie, która jest ustawiona jako /META-INF/wsdl/YourWebServiceName.wsdl względem lokalizacji JavaSource (lub / src, w zależności od konfiguracji projektu) .Podczas procesu kompilacji pliki WSDL i XSD są kopiowane do tej lokalizacji i pakowane w plik JAR. (podobnie do rozwiązania opisanego powyżej przez Bhasakara)
Uwaga: upewnij się, że pliki WSDL używają względnych odniesień do wszelkich zaimportowanych plików XSD, a nie adresów 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>
W wygenerowanym kodzie znajdujemy to:
/** * 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; } }
Być może to też pomoże. Jest to po prostu inne podejście, które nie wykorzystuje podejścia „katalogowego”.
źródło
Wielkie dzięki za odpowiedź Bhaskara Karambelkara, która szczegółowo wyjaśnia i rozwiązuje mój problem. Ale chciałbym również sformułować odpowiedź w trzech prostych krokach dla kogoś, kto spieszy się z naprawą
wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
Utwórz plik xml jax-ws-catalog.xml w META-INF, jak poniżej
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system"> <system systemId="http://localhost/wsdl/yourwsdlname.wsdl" uri="wsdl/yourwsdlname.wsdl" /> </catalog>
Teraz zapakuj słoik. Nie ma już odniesienia do katalogu lokalnego, wszystko jest spakowane i zawiera odwołania
źródło
Dla tych, którzy wciąż szukają tutaj rozwiązania, najłatwiejszym rozwiązaniem byłoby użycie
<wsdlLocation>
bez zmiany kodu. Kroki robocze są podane poniżej:src/main/resource
W pliku pom dodaj zarówno wsdlDirectory, jak i wsdlLocation (nie przegap / na początku wsdlLocation), jak poniżej. Podczas gdy wsdlDirectory jest używany do generowania kodu, a wsdlLocation jest używany w czasie wykonywania do tworzenia dynamicznego serwera proxy.
Następnie w swoim kodzie java (z konstruktorem no-arg):
MyPort myPort = new MyPortService().getMyPort();
Dla kompletności podaję tutaj pełną część generującą kod, z płynnym api w generowanym kodzie.
<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>
źródło
Ci z Was, którzy używają Springa, mogą po prostu odwołać się do dowolnego zasobu classpath-protocol, używając protokołu classpath-protocol. W przypadku wsdlLocation wygląda to następująco:
Należy zauważyć, że nie jest to standardowe zachowanie języka Java. Zobacz też: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html
źródło
Miał dokładnie ten sam problem, który jest tutaj opisany. Niezależnie od tego, co zrobiłem, postępując zgodnie z powyższymi przykładami, aby zmienić lokalizację mojego pliku WSDL (w naszym przypadku z serwera WWW), nadal odwoływałem się do oryginalnej lokalizacji osadzonej w drzewie źródłowym procesu serwera.
Po WIELU godzinach prób debugowania tego zauważyłem, że wyjątek był zawsze wyrzucany z dokładnie tej samej linii (w moim przypadku 41). W końcu dziś rano zdecydowałem się po prostu wysłać mój kod źródłowy klienta do naszego partnera handlowego, aby mogli przynajmniej zrozumieć, jak wygląda kod, ale być może zbudują własny. Ku mojemu zaskoczeniu i przerażeniu znalazłem kilka plików klas zmieszanych z moimi plikami .java w drzewie źródłowym mojego klienta. Jakie dziwne !! Podejrzewam, że były to produkty uboczne narzędzia do tworzenia klientów JAX-WS.
Po usunięciu tych głupich plików .class i całkowitym wyczyszczeniu i odbudowaniu kodu klienta wszystko działa idealnie !! Redonculous !!
YMMV, Andrew
źródło