С момента появления JAX-WS в Java EE создание веб-сервисов SOAP никогда не было таким простым (по сравнению с Spring WS). Всего несколько аннотаций, и все готово. Недостатком всего этого является то, что он всегда исходит из контракта или подхода Java. Хотя во многих средах это так, ситуации бывают, когда это смешанный случай.
Совсем недавно я столкнулся со смешанным делом. Нужно было заменить существующую службу, у которой не было никаких WSDL, но XSD для полезной нагрузки был там. Ниже приведены шаги, которые я выполнил для реализации новой службы из существующих XSD и включенных входящих и исходящих заголовков.
Генерация ObjectFactories из предоставленных XSD-файлов в maven проста, просто добавьте следующий фрагмент в файл pom maven:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>jaxb2-maven-plugin</artifactId> <version>1.6</version> <executions> <execution> <id>xjc</id> <goals> <goal>xjc</goal> </goals> </execution> </executions> <configuration> <bindingFiles> bindings.xjb </bindingFiles> </configuration> </plugin>
Это все, что нужно для создания файлов JAXB. Указанный мной файл привязок позволяет вам настраивать сгенерированные классы. Я склонен конвертировать xsd: DateTime в JodaTime, но это только я.
Далее определение сервисов JAX-WS. В Интернете доступно множество руководств для начала работы с JAX-WS. Нет смысла в этом разбираться. Я обнаружил, что информация о работе с заголовками неоднозначна.
- https://metro.java.net/nonav/1.2/guide/SOAP_headers.html
Решение зависит от ком . солнце . XML . WS . Занятия для разработчиков. Не туда, куда я хочу пойти.
- http://www-01.ibm.com/support/knowledgecenter/SS7K4U_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/twbs_cookiejaxws.html
Предлагает решение, в котором заголовки устанавливаются отдельно. Даже не отвечает, как делать входящие заголовки. - http://stackoverflow.com/questions/830691/how-do-i-add-a-soap-header-using-java-jax-ws
Просто пример ответов, которые доступны в stackoverflow . Решение, представленное здесь, является наиболее распространенным.
Все предоставленные решения помогут получить заголовки в сообщении. Чего вы не находите, так это решения, использующего аннотацию @WebParam в списке аргументов веб-службы. У аннотации есть два важных поля для поддержки заголовка; заголовок и режим .
Установка поля заголовка в true добавит это к заголовочной части сообщения мыла. флаг режима допускает следующие значения:
- IN
Inbound - OUT
Outbound - INOUT
в и исходящих.
Первые два просты в использовании. последнее, INOUT имеет немного больше.
При использовании значения WebParam.Mode.INOUT изменения значительны, так как используемый вами контейнер не может генерировать файлы WSDL и XSD. Ошибка, которую вы получаете, неоднозначна. Конечный результат ваш WSDL не генерируется, следовательно, сервис недоступен. Ключ при использовании режима INOUT — это универсальный класс javax.xml.ws.Holder <T> . Когда параметр находится внутри этого типа. WSDL генерируется правильно.
Результирующий метод @WebMethod:
@WebMethod( action = "ServiceName", operationName = "operation" ) public MyResponse operation( @WebParam(mode = WebParam.Mode.INOUT, header = true, name = "JaxbHeader", targetNamespace = "http://www.elucidator.nl/header/v1.0") final Holder headerHolder, @WebParam(mode = WebParam.Mode.IN, name = "data") final JaxbPayload payload) throws MyServiceException { //SNIP if (headerHolder.value.flag) { headerHolder.value.field = "SomeValue"; return responseObject; }
Доступ к значениям в объекте заголовка прямой. при изменении значений ответ содержит измененные значения. Благодаря этому решению нет необходимости писать собственные реализации SOAPHandler для заголовков.
Сгенерированный WSDL будет:
<definitions xmlns:ns1="..." xmlns:tns="..." xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" name="MyService" targetNamespace="..." xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> //SNIP </types> <message name="operation"> <part name="parameters" element="tns:operation"/> <part name="jaxbHeader" element="ns1:JaxbHeader"/> </message> <message name="operationResponse"> <part name="result" element="tns:operationResponse"/> <part name="JaxbHeader" element="ns1:JaxbHeader"/> </message> <portType name="ServiceName"> <operation name="insert" parameterOrder="parameters JaxbHeader"> <input message="tns:operation" wsam:Action="operation"/> <output message="tns:operationResponse" wsam:Action="http://www.elucidator.nl/ws/v1.0/operationResponse"/> </operation> </portType> <binding name="ServiceNameBinding" type="tns:ServiceName"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="insert"> <soap:operation soapAction="operation"/> <input> <soap:body parts="parameters" use="literal"/> <soap:header message="tns:operation" part="JaxbHeader" use="literal"/> </input> <output> <soap:body parts="result" use="literal"/> <soap:header message="tns:operationResponse" part="JaxbHeader" use="literal"/> </output> </operation> </binding> <service name="ServiceName"> <port name="ServiceNamePort" binding="tns:ServicePortBinding"> <soap:address location="http://localhost:9081/Service"/> </port> </service> </definitions>
Как видите, прекрасно сгенерированный WSDL, который содержит информацию о ожидаемых и возвращаемых заголовках.
Однако у этого решения есть один небольшой недостаток. Когда выдается исключение, у вас больше нет доступа к заголовкам. У меня есть решение для этого, реализация обработчика, который перехватывает запрос, сохраняет заголовок и изменяет ответ на ошибку в методе handleFault . Но это тема для другого поста.
Оригинал можно найти на: Elucidator