GlassFish 3.1.2 is Full of MOXy (EclipseLink JAXB)
In this post I will introduce how MOXy can be leveraged to create a JAX-WS service. In future posts I will cover more of the extensions in greater detail.
GlassFish can be downloaded from the following link:
For this post we will implement a simple service that finds a customer by ID. As this is just a "Hello World" type example the service will always return a customer with the name "Jane Doe".
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | package blog.jaxws.service; import javax.jws.*; import blog.jaxws.model.Customer; @WebService public class FindCustomer { @WebMethod public Customer findCustomer( int id) { Customer customer = new Customer(); customer.setId(id); customer.setFirstName( "Jane" ); customer.setLastName( "Doe" ); return customer; } } |
WEB-INF/sun-jaxws.xml
There are multiple ways to specify MOXy as the JAXB provider. My preference is to use the sun-jaxws.xml file that is located in the WEB-INF directory.
01 02 03 04 05 06 07 08 09 10 | <? xml version = "1.0" encoding = "UTF-8" ?> < endpoints version = "2.0" > < endpoint name = 'FindCustomer' implementation = 'blog.jaxws.service.FindCustomer' url-pattern = '/FindCustomerService' databinding = 'eclipselink.jaxb' /> </ endpoints > |
Model
When MOXy is specified as the JAXB provider we can leverage all of its mapping extensions. In this example we will use @XmlPath to do XPath based mapping.
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 | package blog.jaxws.model; import javax.xml.bind.annotation.*; import org.eclipse.persistence.oxm.annotations.XmlPath; @XmlAccessorType (XmlAccessType.FIELD) @XmlType (propOrder={ "firstName" , "lastName" }) public class Customer { @XmlAttribute private int id; @XmlPath ( "personal-info/first-name/text()" ) private String firstName; @XmlPath ( "personal-info/last-name/text()" ) private String lastName; public int getId() { return id; } public void setId( int id) { this .id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this .firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this .lastName = lastName; } } |
WSDL
Below is the WSDL that was generated for this service:
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 | <? xml version = "1.0" encoding = "UTF-8" ?> <!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is Metro/2.2-b13 (branches/2.2-6964; 2012-01-09T18:04:18+0000) JAXWS-RI/2.2.6-promoted-b20 JAXWS/2.2 svn-revision#unknown. --> <!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is Metro/2.2-b13 (branches/2.2-6964; 2012-01-09T18:04:18+0000) JAXWS-RI/2.2.6-promoted-b20 JAXWS/2.2 svn-revision#unknown. --> < definitions xmlns:wsu = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp = "http://www.w3.org/ns/ws-policy" xmlns:wsp1_2 = "http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam = "http://www.w3.org/2007/05/addressing/metadata" xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns = "http://service.jaxws.blog/" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" xmlns = "http://schemas.xmlsoap.org/wsdl/" targetNamespace = "http://service.jaxws.blog/" name = "FindCustomerService" > < types > < xsd:schema > < xsd:import namespace = "http://service.jaxws.blog/" schemaLocation = "http://www.example.com:8080/Blog-JAXWS2/FindCustomerService?xsd=1" /> </ 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 wsam:Action = "http://service.jaxws.blog/FindCustomer/findCustomerRequest" message = "tns:findCustomer" /> < output wsam:Action = "http://service.jaxws.blog/FindCustomer/findCustomerResponse" message = "tns:findCustomerResponse" /> </ operation > </ portType > < binding name = "FindCustomerPortBinding" type = "tns:FindCustomer" > < 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 Schema
Below is the XML schema referenced by the WSDL that was generated for the model. Notice how it includes the "personal-info" element that was specified in the @XmlPath annotation.
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 | <? xml version = "1.0" encoding = "UTF-8" ?> <!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is Metro/2.2-b13 (branches/2.2-6964; 2012-01-09T18:04:18+0000) JAXWS-RI/2.2.6-promoted-b20 JAXWS/2.2 svn-revision#unknown. --> < xsd:complexType name = "findCustomerResponse" > < xsd:sequence > < xsd:element name = "return" type = "ns0:customer" minOccurs = "0" /> </ xsd:sequence > </ xsd:complexType > < 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:element name = "findCustomerResponse" type = "ns0:findCustomerResponse" /> < xsd:element name = "findCustomer" type = "ns0:findCustomer" /> </ xsd:schema > |
Service Request
Below is what a request to our service looks like:
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 > |
Service Response
The response leverages the @XmlPath annotation we used on the Customer class to map the firstName and lastName properties to XML.
01 02 03 04 05 06 07 08 09 10 11 12 13 | <? xml version = "1.0" encoding = "UTF-8" ?> < S:Body > < return id = "123" > < personal-info > < first-name >Jane</ first-name > < last-name >Doe</ last-name > </ personal-info > </ return > </ ns0:findCustomerResponse > </ S:Body > </ S:Envelope > |
Further Reading
If you enjoyed this post, then you may be interested in:
- EclipseLink MOXy is the JAXB Provider in WebLogic Server 12c
- XPath Based Mapping – Geocode Example
- Mapping Objects to Multiple XML Schemas – Weather Example
- MOXy’s XML Metadata in a JAX-RS Service
- JPA Entities to XML – Bidirectional Relationships
Reference: GlassFish 3.1.2 is Full of MOXy (EclipseLink JAXB) from our JCG partner Blaise Doughan at the Java XML & JSON Binding blog.