Проблема в том, что мне нужно создать клиент веб-службы из предоставленного мне файла. Я сохранил этот файл в локальной файловой системе, и хотя я храню файл WSDL в нужной папке файловой системы, все в порядке. Когда я развертываю его на сервере или удаляю WSDL из папки файловой системы, прокси не может найти WSDL и выдает ошибку. Я поискал в Интернете и нашел следующие сообщения, но мне не удалось заставить его работать:
JAX-WS Загрузка WSDL из 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
Я использую 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: не удалось получить доступ к WSDL в: файле: /WEB-INF/wsdl/client/SOAService.wsdl. Ошибка: \ WEB-INF \ wsdl \ client \ SOAService.wsdl (не удается найти путь)
Итак, в первую очередь, нужно ли мне обновить wsdllocation прокси-класса? Тогда как мне сообщить классу SOAService в WEB-INF / classes / com / ibm / eci / soaservice, что нужно искать WSDL в \ WEB-INF \ wsdl \ client \ SOAService.wsdl?
EDITED : я нашел эту другую ссылку - http://jianmingli.com/wp/?cat=41 , в которой говорится, что WSDL нужно поместить в путь к классам. Стыдно спросить: как мне поместить это в путь к классам веб-приложения?
Ответы:
Лучше всего использовать jax-ws-catalog.xml.
Когда вы компилируете локальный файл WSDL, переопределите расположение WSDL и установите для него что-то вроде
Не волнуйтесь, это всего лишь URI, а не URL, то есть вам не обязательно иметь доступ к WSDL по этому адресу.
Вы можете сделать это, передав параметр wsdllocation в wsdl компилятору 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; }
Файл уведомления: // изменен на http: // в конструкторе URL.
Теперь идет jax-ws-catalog.xml. Без jax-ws-catalog.xml jax-ws действительно попытается загрузить WSDL из местоположения
и не получится, поскольку такой WSDL не будет доступен.Но с jax-ws-catalog.xml вы можете перенаправить jax-ws на локально упакованный WSDL всякий раз, когда он пытается получить доступ к 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 из
, он должен загрузить его с локального пути wsdl / SOAService.wsdl.Куда теперь поместить wsdl / SOAService.wsdl и jax-ws-catalog.xml? Это вопрос на миллион долларов, не так ли?
Он должен находиться в каталоге META-INF jar-файла вашего приложения.
так что-то вроде этого
Таким образом, вам даже не нужно переопределять URL-адрес в вашем клиенте, который обращается к прокси. WSDL берется из вашего JAR, и вам не нужно иметь жестко заданные пути файловой системы в вашем коде.
Дополнительная информация о jax-ws-catalog.xml http://jax-ws.java.net/nonav/2.1.2m1/docs/catalog-support.html
надеюсь, это поможет
источник
Еще один успешный подход - сгенерировать код прокси-сервера WS-клиента с помощью wsimport (из Ant в качестве задачи Ant) и указать атрибут wsdlLocation.
<wsimport debug="true" keep="true" verbose="false" target="2.1" sourcedestdir="${generated.client}" wsdl="${src}${wsdl.file}" wsdlLocation="${wsdl.file}"> </wsimport>
Поскольку мы запускаем это для проекта с несколькими WSDL, скрипт динамически разрешает значение $ (wsdl.file}, которое настроено как /META-INF/wsdl/YourWebServiceName.wsdl относительно местоположения JavaSource (или / src, в зависимости от того, как настроен ваш проект). В процессе сборки файлы WSDL и XSD копируются в это место и упаковываются в файл JAR (аналогично решению, описанному Бхасакаром выше)
Примечание: убедитесь, что файлы WSDL используют относительные ссылки на любые импортированные XSD, а не 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>
В сгенерированном коде мы находим следующее:
/** * 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; } }
Возможно, это тоже может помочь. Это просто другой подход, в котором не используется «каталогный» подход.
источник
Большое спасибо за ответ Бхаскара Карамбелкара, который подробно объясняет и исправляет мою проблему. Но также я хотел бы перефразировать ответ в три простых шага для тех, кто спешит исправить
wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
Создайте xml-файл jax-ws-catalog.xml в META-INF, как показано ниже.
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system"> <system systemId="http://localhost/wsdl/yourwsdlname.wsdl" uri="wsdl/yourwsdlname.wsdl" /> </catalog>
Теперь упакуйте банку. Больше никаких ссылок на локальный каталог, все это упаковано и упоминается внутри
источник
Для тех, кто все еще пытается найти решение, самым простым решением будет использование
<wsdlLocation>
без изменения кода. Рабочие шаги приведены ниже:src/main/resource
В файле pom добавьте wsdlDirectory и wsdlLocation (не пропустите / в начале wsdlLocation), как показано ниже. В то время как wsdlDirectory используется для генерации кода, а wsdlLocation используется во время выполнения для создания динамического прокси.
Затем в вашем java-коде (без конструктора без аргументов):
MyPort myPort = new MyPortService().getMyPort();
Для полноты я предоставляю здесь полную часть генерации кода с беглым api в сгенерированном коде.
<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>
источник
Те из вас, кто использует Spring, могут просто сослаться на любой ресурс classpath, используя протокол classpath. Итак, в случае wsdlLocation это становится:
Обратите внимание, что это нестандартное поведение Java. См. Также: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html.
источник
Была точно такая же проблема, которая описана здесь. Независимо от того, что я сделал, следуя приведенным выше примерам, чтобы изменить расположение моего файла WSDL (в нашем случае с веб-сервера), он по-прежнему ссылался на исходное расположение, встроенное в исходное дерево серверного процесса.
После МНОГИХ часов попытки отладить это, я заметил, что исключение всегда выбрасывается из одной и той же строки (в моем случае 41). Наконец, сегодня утром я решил просто отправить свой исходный код клиента нашему торговому партнеру, чтобы они могли хотя бы понять, как выглядит код, но, возможно, создать свой собственный. К своему шоку и ужасу я обнаружил в дереве исходных кодов клиента кучу файлов классов, смешанных с моими файлами .java. Как странно !! Я подозреваю, что это был побочный продукт инструмента построения клиентов JAX-WS.
Как только я удалил эти глупые файлы .class и выполнил полную очистку и пересборку клиентского кода, все заработало отлично !! Чудовищно !!
YMMV, Андрей
источник