В предыдущих статьях я демонстрировал, как EclipseLink JAXB (MOXy) напрямую интегрируется в реализации JAX-WS в WebLogic (по состоянию на 12.1.1) и в GlassFish (по состоянию на 3.1.2) . В этой статье я продемонстрирую, как использовать MOXy на любом сервере приложений с помощью класса провайдера JAX-WS.
Веб-сервис
Механизм Provider в JAX-WS предоставляет вам способ создания веб-службы с прямым доступом к XML. С помощью аннотации @ServiceMode вы можете указать, хотите ли вы весь XML из сообщения или только полезную нагрузку.
FindCustomerService
Вся магия происходит в методе invoke . Так как мы указали PAYLOAD в качестве сервисного режима, входные данные будут экземпляром Source, который представляет тело сообщения. Все реализации JAXB (JSR-222) могут демонтироваться из источника, поэтому мы сделаем это для реализации запроса. После того, как мы выполним нашу бизнес-логику, нам нужно вернуть тело ответа как экземпляр Source . Чтобы достичь этого, мы обернем наши объекты ответа в экземпляр JAXBSource .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package blog.jaxws.provider;import javax.xml.bind.*;import javax.xml.bind.util.JAXBSource;import javax.xml.transform.Source;import javax.xml.ws.*;@ServiceMode(Service.Mode.PAYLOAD)@WebServiceProvider( portName = 'FindCustomerPort', serviceName = 'FindCustomerService', wsdlLocation = 'WEB-INF/wsdl/FindCustomerService.wsdl')public class FindCustomerService implements Provider<Source> { private JAXBContext jaxbContext; public FindCustomerService() { try { jaxbContext = JAXBContext.newInstance(FindCustomerResponse.class, FindCustomerRequest.class); } catch (JAXBException e) { throw new WebServiceException(e); } } @Override public Source invoke(Source request) throws WebServiceException { try { Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); FindCustomerRequest fcRequest = (FindCustomerRequest) unmarshaller .unmarshal(request); Customer customer = new Customer(); customer.setId(fcRequest.getArg0()); customer.setFirstName('Jane'); customer.setLastName('Doe'); FindCustomerResponse response = new FindCustomerResponse(); response.setValue(customer); return new JAXBSource(jaxbContext, response); } catch (JAXBException e) { throw new WebServiceException(e); } }} |
МОКСИ как провайдер JAXB
Чтобы указать, что MOXy должен использоваться в качестве провайдера JAXB, нам нужно включить файл с именем jaxb.properties, который находится в том же пакете, что и наша модель домена, со следующей записью (см. Определение EclipseLink MOXy в качестве вашего провайдера JAXB ).
|
1
|
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory |
WSDL
Ниже приведен WSDL, соответствующий нашему веб-сервису. Одним из недостатков использования подхода Provider является то, что реализация JAX-WS не может автоматически сгенерировать его для нас (см. GlassFish 3.1.2 полон MOXy (EclipseLink JAXB) ). WSDL необходим, поскольку он определяет контракт для клиента. Он даже может быть использован для генерации клиента.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
<?xml version='1.0' encoding='UTF-8'?><definitions name='FindCustomerService'> <types> <xsd:schema> <xsd:import schemaLocation='FindCustomerService.xsd'/> </xsd:schema> </types> <message name='findCustomer'> <part name='parameters' element='tns:findCustomer'/> </message> <message name='findCustomerResponse'> <part name='parameters' element='tns:findCustomerResponse'/> </message> <portType name='FindCustomer'> <operation name='findCustomer'> <input message='tns:findCustomer'/> <output message='tns:findCustomerResponse'/> </operation> </portType> <binding name='FindCustomerPortBinding' type='tns:FindCustomer'> <soap:binding style='document'/> <operation name='findCustomer'> <soap:operation soapAction=''/> <input> <soap:body use='literal'/> </input> <output> <soap:body use='literal'/> </output> </operation> </binding> <service name='FindCustomerService'> <port name='FindCustomerPort' binding='tns:FindCustomerPortBinding'> </port> </service></definitions> |
XML-схема
Ниже приведена схема XML, которая соответствует полезной нагрузке нашего сообщения. Одним из недостатков использования подхода Provider является то, что реализация JAX-WS не может напрямую использовать JAXB для автоматической генерации XML-схемы, поэтому нам необходимо предоставить ее.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
<?xml version='1.0' encoding='UTF-8'?><xsd:schema <xsd:element name='findCustomerResponse' type='ns0:findCustomerResponse' /> <xsd:complexType name='findCustomerResponse'> <xsd:sequence> <xsd:element name='return' type='ns0:customer' minOccurs='0' /> </xsd:sequence> </xsd:complexType> <xsd:element name='findCustomer' type='ns0:findCustomer' /> <xsd:complexType name='findCustomer'> <xsd:sequence> <xsd:element name='arg0' type='xsd:int' /> </xsd:sequence> </xsd:complexType> <xsd:complexType name='customer'> <xsd:sequence> <xsd:element name='personal-info' minOccurs='0'> <xsd:complexType> <xsd:sequence> <xsd:element name='first-name' type='xsd:string' minOccurs='0' /> <xsd:element name='last-name' type='xsd:string' minOccurs='0' /> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name='id' type='xsd:int' use='required' /> </xsd:complexType></xsd:schema> |
Объекты запроса
Выделенная часть XML-сообщения ниже — это то, что мы собираемся получить в нашем провайдере, как в случае с источником . Мы создадим модель JAXB для сопоставления с этим разделом.
|
1
2
3
4
5
6
7
8
9
|
<?xml version='1.0' encoding='UTF-8'?> <S:Header/> <S:Body> <arg0>123</arg0> </ns2:findCustomer> </S:Body></S:Envelope> |
FindCustomerRequest
Корневой элемент находится в другом пространстве имен XML, чем остальная часть тела. Мы будем использовать аннотацию @XmlRootElement для указания пространства имен (см .: JAXB & Namespaces ).
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
package blog.jaxws.provider;import javax.xml.bind.annotation.*;@XmlRootElement( name='findCustomer')public class FindCustomerRequest { private int arg0; public int getArg0() { return arg0; } public void setArg0(int arg0) { this.arg0 = arg0; }} |
Объекты ответа
Выделенная часть XML-сообщения ниже — это то, что мы собираемся вернуть нашему провайдеру, как в случае с источником . Мы создадим модель JAXB для сопоставления с этим разделом.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
<S:Header /> <S:Body> <ns0:findCustomerResponse <return id='123'> <personal-info> <first-name>Jane</first-name> <last-name>Doe</last-name> </personal-info> </return> </ns0:findCustomerResponse> </S:Body></S:Envelope> |
FindCustomerResponse
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
package blog.jaxws.provider;import javax.xml.bind.annotation.*;public class FindCustomerResponse { private Customer value; @XmlElement(name='return') public Customer getValue() { return value; } public void setValue(Customer value) { this.value = value; }} |
Клиент
Одной из многих причин использования MOXy является его отображение на основе пути (см .: XPath Based Mapping ). Ниже приведен пример того, как это указано с помощью аннотации @XmlPath .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
package blog.jaxws.provider;import javax.xml.bind.annotation.*;import org.eclipse.persistence.oxm.annotations.XmlPath;@XmlType(propOrder = { 'firstName', 'lastName' })public class Customer { private int id; private String firstName; private String lastName; @XmlAttribute public int getId() { return id; } public void setId(int id) { this.id = id; } @XmlPath('personal-info/first-name/text()') public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlPath('personal-info/last-name/text()') public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; }} |
Ссылка: Использование MOXy в вашем веб-сервисе через провайдера JAX-WS от нашего партнера по JCG Блэза Дафана из блога Java XML & JSON Binding .