JAX-WS Hello World Example – Document Style
In this example we are going to see how to create, deploy and consume Web Services using JAX-WS. JAX-WS is a fine tool for creating Web Services and it’s included in the JDK since JDK 1.6.
You are going to see how easy it is to create and deploy Web Services using Document Style. What you need to run this example is only JDK 1.6 or above and that’s that.
The basic architecture of a JAX-WS Web Service consists of two main parts:
- A Web Service Endpoint: It is a connection point where pages and Web Services are exposed to consumers and clients.
- A Web Service Client: The program that makes use of the published Web Service from the above Endpoint.
1. Document vs RPC style
In the previous article, JAX-WS Hello World Example – RPC Style we used RPC Style for our SOAP Binding. RPC and Document are two different ways to encode and construct SOAP messages.
In short, RPC style SOAP messages contain and XML representation of the method’s call in their body, and use the name of the method and its parameters to construct an XML tree that represents the method’s call stack.
In Document style, the SOAP body contais an XML document that can be validated against a defined XML schema. This is a more customizable and flexible approach as the protocol relies on the pre-defined schema to determine the structure of the SOAP message which can be done on the fly. And it means that you are free to customize the SOAP messages as much as you want.
2. JAX-WS Web Service End Point
In order to create a Web Service Endpoint:
- First you have to create a Web Service Endpoint Interface. This interface will contain the declerations of all the methods you want to include in the Web Service.
- Then you have to create a class that actually implements the above interface, which will be your Endpoint implementation.
- Finally you create your Endpoint publisher which actually deploys the web service and creates and publishes the endpoint for the specified implementor object at a given address. The necessary server infrastructure will be created and configured by the JAX-WS implementation. You have to run the publisher to make your Web Service available to clients.
Web Service Endpoint Interface (SEI)
WebServiceInterface.java:
package com.javacodegeeks.enterprise.ws.jaxws; import javax.jws.WebMethod; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import javax.jws.soap.SOAPBinding.Style; @WebService @SOAPBinding(style = Style.DOCUMENT) public interface WebServiceInterface{ @WebMethod String getHelloWorldAsString(String name); }
Web Service Endpoint Implementation
WebServiceImpl.java:
package com.javacodegeeks.enterprise.ws.jaxws; import javax.jws.WebService; @WebService(endpointInterface = "com.javacodegeeks.enterprise.ws.WebServiceInterface") public class WebServiceImpl implements WebServiceInterface{ @Override public String getHelloWorldAsString(String str) { return "Hello World of JAX-WS " + str; } }
Web Service Endpoint Publisher
WebServicePublisher.java:
package com.javacodegeeks.enterprise.ws.jaxws; import javax.xml.ws.Endpoint; import com.javacodegeeks.enterprise.ws.WebServiceImpl; public class WebServicePublisher{ public static void main(String[] args) { Endpoint.publish("http://localhost:8888/webservice/helloworld", new WebServiceImpl()); } }
Now when you run the publisher the Web Service will be available to the clients, deployed in the URL:
http://localhost:8888/webservice/helloworld
If you put that address to your browser, you should get this :
And this is the wsdl file that is automatically created (published in http://localhost:8888/webserive/helloworld?wsdl
):
WSDL:
<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. --> <!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. --> <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://jaxws.ws.enterprise.javacodegeeks.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://jaxws.ws.enterprise.javacodegeeks.com/" name="WebServiceImplService"> <types> <xsd:schema> <xsd:import namespace="http://jaxws.ws.enterprise.javacodegeeks.com/" schemaLocation="http://localhost:8888/webservice/helloworld?xsd=1" /> </xsd:schema> </types> <message name="getHelloWorldAsString"> <part name="parameters" element="tns:getHelloWorldAsString" /> </message> <message name="getHelloWorldAsStringResponse"> <part name="parameters" element="tns:getHelloWorldAsStringResponse" /> </message> <portType name="WebServiceInterface"> <operation name="getHelloWorldAsString"> <input wsam:Action="http://jaxws.ws.enterprise.javacodegeeks.com/WebServiceInterface/getHelloWorldAsStringRequest" message="tns:getHelloWorldAsString" /> <output wsam:Action="http://jaxws.ws.enterprise.javacodegeeks.com/WebServiceInterface/getHelloWorldAsStringResponse" message="tns:getHelloWorldAsStringResponse" /> </operation> </portType> <binding name="WebServiceImplPortBinding" type="tns:WebServiceInterface"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> <operation name="getHelloWorldAsString"> <soap:operation soapAction="" /> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> <service name="WebServiceImplService"> <port name="WebServiceImplPort" binding="tns:WebServiceImplPortBinding"> <soap:address location="http://localhost:8888/webservice/helloworld" /> </port> </service> </definitions>
3. Java Web Service Endpoint using wsgen tool
When runing the above publisher, it is possible to hit an error like:
Exception in thread "main" com.sun.xml.internal.ws.model.RuntimeModelerException: runtime modeler error: Wrapper class com.javacodegeeks.enterprise.ws.jaxws.GetHelloWorldAsString is not found. Have you run APT to generate them?
That is because Document style SOAP requiers mapping classes for the XML schemas (it’s the pre-defined XML schemas we talked about in the introduction), in order to generate SOAP requests that can be validated, and be able to process SOAP responses .
To generate the necessary files you can use wsgen
tool which is located in your JDK_HOME/bin
folder. To generate the necessary mapping files, I issued the following command :
wsgen -keep -cp . com.javacodegeeks.enterprise.ws.jaxws.WebServiceImpl -s F:\nikos7\workspace\JAX-WS-RPC\src\
Here is the picture of the terminal:
The warning that we got gives a possible explanation on why our program worked without these mapping classes. It is possible that JAX-WS is using javac to gather all the information needed to generate the wsdl that is necessary, without having to create mapping classes. But if you want to further customize the format of the SOAP message it is always safer to generete the mapping classes.
These are the generated source files:
GetHelloWorldAsString.java:
package com.javacodegeeks.enterprise.ws.jaxws; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "getHelloWorldAsString", namespace = "http://jaxws.ws.enterprise.javacodegeeks.com/") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "getHelloWorldAsString", namespace = "http://jaxws.ws.enterprise.javacodegeeks.com/") public class GetHelloWorldAsString { @XmlElement(name = "arg0", namespace = "") private String arg0; /** * * @return * returns String */ public String getArg0() { return this.arg0; } /** * * @param arg0 * the value for the arg0 property */ public void setArg0(String arg0) { this.arg0 = arg0; } }
GetHelloWorldAsStringResponse.java:
package com.javacodegeeks.enterprise.ws.jaxws; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "getHelloWorldAsStringResponse", namespace = "http://jaxws.ws.enterprise.javacodegeeks.com/") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "getHelloWorldAsStringResponse", namespace = "http://jaxws.ws.enterprise.javacodegeeks.com/") public class GetHelloWorldAsStringResponse { @XmlElement(name = "return", namespace = "") private String _return; /** * * @return * returns String */ public String getReturn() { return this._return; } /** * * @param _return * the value for the _return property */ public void setReturn(String _return) { this._return = _return; } }
4. Web Service Client
This is client that consumes the above Web Service, written in Java:
WebServiceClient.java:
package com.javacodegeeks.enterprise.ws.client; import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.Service; import com.javacodegeeks.enterprise.ws.jaxws.WebServiceInterface; public class WebServiceClient{ public static void main(String[] args) throws Exception { URL wsdlUrl = new URL("http://localhost:8888/webservice/helloworld?wsdl"); //qualifier name ... QName qname = new QName("http://jaxws.ws.enterprise.javacodegeeks.com/", "WebServiceImplService"); Service service = Service.create(wsdlUrl, qname); WebServiceInterface helloService = service.getPort(WebServiceInterface.class); System.out.println(helloService.getHelloWorldAsString("- This is Java Code Geeks")); } }
The output of the above program would be:
Hello World JAX-WS - This is Java Code Geeks
This was an example on JAX-WS Document Style Web Services. Download the Eclipse Project of this tutorial: JAX-WS-Document.zip