Изменение URL-адреса клиента webservice, сгенерированного с помощью wsimport

Я пытаюсь написать модуль для приложения Java, который обращается к веб-сервису, описываемому WSDL. Источник WSDL был загружен прямо из того, что я считаю веб-сервисом ASP.NET; URL-адрес службы заканчивается расширением .asmx и просмотр URL-адреса службы в браузере показывает ссылку, которая может быть использована для загрузки WSDL.

Ключевым требованием для меня является возможность отключить URL-адрес службы без перекомпиляции. Указанный мне URL-адрес, очевидно, является тестовым сервером, и я знаю, что на производстве мне будет предоставлен URL-адрес для создания. Я также хотел бы иметь возможность самостоятельно создавать макетный сервер для тестирования и сохранять возможность указывать новый URL-адрес в будущем без перекомпиляции, если служба будет перемещена. На самом деле, я хотел бы, чтобы установка нашего приложения позволяла создавать несколько экземпляров веб-службы на разных URL-адресах.

Но моя концепция, похоже, не соответствует тому, что делает инструмент wsimport для меня. Следуя f1sh answer здесь, я сгенерировал Java-код из загруженного WSDL с помощью этой команды:

wsimport -Xnocompile -keep -b binding.xml wsdlFile.wsdl

Я нахожу, что сгенерированный код имеет жесткую ссылку на мой загруженный wsdlFile.wsdl, который содержит URL-адрес службы. Наше приложение не будет работать таким образом, чтобы его можно было настроить, отредактировав файл WSDL во время выполнения. Мне нужно, чтобы код был скомпилирован в мое приложение во время сборки и может иметь URL-адрес службы во время создания экземпляра.

Я не совсем уверен, почему WSDL даже нужно разбирать во время выполнения; я понял, что WSDL предоставляет достаточную информацию для генерации кода, который может получить доступ к веб-сервису, поэтому я не уверен, что он предоставляет сгенерированному коду, отличному от URL-адреса службы, и я не уверен, почему URL-адрес службы не указан в конструктор или настраиваемый с помощью метода в созданном классе webservice. Мне что-то не хватает.

Какова общая практика для этого сценария? Большинство людей регенерируют код для каждого отдельного URL-адреса, который они будут использовать? Создается ли код во время выполнения? Есть ли другой инструмент WSDL, который я могу использовать, который построит клиентский код с настраиваемым URL?

Ответ 1

Этот подход требует от меня также предоставить объект javax.xml.namespace.QName, который я пока не понимаю, в качестве второго аргумента.

Скопируйте один из вашего сгенерированного источника. QName - это квалифицированное имя XML - "уникальная" идентичность.

Я до сих пор не понимаю, зачем нужен WSDL во время выполнения.

Не могу сказать, что знаю точно, но WSDL - это в основном схема. Предоставляя его, я предполагаю, что вы дадите JAX-WS механизм для проверки ответа SOAP. Я не думаю, что привязки JAXB достаточно, чтобы сделать это.

Я всегда использую конструктор с двумя аргументами в сгенерированном сервисе для предоставления URL через метод ClassLoader.getResource для встраивания WSDL в мой jar. Как и в любой схеме, использование URL-адреса удаленной или файловой системы для этой цели глупо, но не оптимально.

Посмотрите этот вопрос о том, как установить конечную точку во время выполнения:

HelloService service = new HelloService();
Hello port = service.getHelloPort();
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider.getRequestContext().put(
      BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
      "http://foo:8086/HelloWhatever");
String response = port.sayHello(name);

Ответ 2

Этот ответ ускользал от меня на пару дней, но как-то акт написания вопроса всегда фокусирует меня на поиске ответа, и еще несколько веб-сайтов указали на это:

http://www.fransvanbuul.net/?p=98

Кажется, что wsimport создал класс com.example.WebService, который расширяет javax.xml.ws.Service. Этот класс WebService имеет два конструктора. Конструктор no-arg жестко закодирован с URL-адресом file://, с помощью которого создается исходный WSDL. (Я полагаю, что если бы я предоставил https://URL-адрес в командной строке wsimport, это был бы URL-адрес, который был жестко запрограммирован.) В качестве альтернативы я могу использовать конструктор с двумя аргументами и предоставить URL-адрес WSDL во время создания экземпляра! Этот подход требует, чтобы я также предоставил объект javax.xml.namespace.QName, который я еще не понял, как второй аргумент.

Использование этого конструктора с двумя аргументами, вероятно, решит мою проблему.

Кажется, что wsimport, который я использую из JDK 1.6, является частью пакета JAX-WS. В последних версиях JDK 1.6 содержится JAX-WS 2.1, и JAX-WS 2.2 рассмотрит трудности, которые я поднимаю в этом вопросе.

Я буду рад принять любой ответ, объясняющий некоторые или всю оставшуюся ситуацию. Я все еще не понимаю, почему WSDL необходим во время выполнения. Более практично, это помогло бы мне кому-то показать мне, как использовать конструктор с двумя аргументами, или как сгенерировать мой код с помощью JDK 1.6 и JAX-WS 2.2.