Задача:
В JAX-WS-веб-сервисе (используется имплементация JAX-WS RI) есть несколько методов, возвращающих объекты одного типа (пусть это будет класс OperResultClass):
@WebMethod(operationName = "operationA")
public OperResultClass operationA(){...}
@WebMethod(operationName = "operationB")
public OperResultClass operationB(){...}
@WebMethod(operationName = "operationC")
public OperResultClass operationC(){...}...
Необходимо, чтобы XML, получаемый на их выходе, выглядел так:
<MyResponseWrapperTag xmlns="http://soap.response">
<MyResponseTag>
<!-- содержимое объекта-ответа -->
</MyResponseTag>
</MyResponseWrapperTag>
Т.е. необходимо задать для всех методов:
- Имя наружного тега и его пространство имен
- Имя внутреннего тега и его пространство имен
Решение:
Второй пункт делается просто: каждый метод аннотируется следующим образом:
@WebResult(name="MyResponseTag", targetNamespace="http://soap.response")
После этого мы будем иметь правильный внутренний тег, а вот наружный будет генерироваться JAX-WS`ом автоматически, основываясь на имени метода (он будет состоять из имени метода + "Response").
Для задания имени наружного тега используется аннотация @ResponseWrapper. Но использовать её так:
@ResponseWrapper(не получится - будет валиться исключение:
localName="MyResponseWrapperTag",
targetNamespace="http://soap.response"
)
Two classes have the same XML type name "{http://soap.response}MyResponseWrapperTag". Use @XmlType.name and @XmlType.namespace to assign different names to them.
Тут дело в том, что для оберток вокруг ответа JAX-WS генерирует свои классы, по одному на каждый метод. Т.о, для каждого веб-метода будет использоваться свой класс, в то время как из-за @ResponseWrapper всем им будет назначен одно и тот же имя XML-типа.
Выход из ситуации - самостоятельно задавать имя класса-обертки, чтобы JAX-WS не генерировал своих классов. Делается это следующим образом:
@ResponseWrapper( className="my.MyResponseWrapper",Теперь нужно создать этот самый класс-wrapper "my.MyResponseWrapper". Он будет выглядеть примерно так:
localName="MyResponseWrapperTag",
targetNamespace="http://soap.response"
)
@XmlType(name="MyResponseWrapperType",namespace="http://soap.response")
@XmlAccessorType(XmlAccessType.FIELD)
public class MyResponseWrapper{
@XmlElement(name="MyResponseTag",namespace="http://soap.response")
public OperResultClass MyResponseTag;
}
Здесь важно, чтобы параметры аннотации @XmlElement совпадали с таковыми в аннотации @WebResult метода. Namespace можно не указывать, если он задан на уровне пакета в package-info.java:
@XmlSchema(namespace = "http://soap.response", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package my;
import javax.xml.bind.annotation.XmlSchema;
Комментариев нет:
Отправить комментарий