JAX-WS Basic example – Document Style
We have seen RPC style in previous article.
In this article, we will see Document style example using JAX-WS
The Style indicates how exactly the SOAP message body is structured.
The Document style indicates that the SOAP message body contains a XML document which can be validated against pre-defined XML schema document.
RPC style indicates that the SOAP message body contains an XML representation of a method call and uses the names of the method and its parameters to generate XML structures that represents a method’s call stack.
Read more about RPC ,Document and other binding style in soap message binding style article
To achieve Document style in JAX-WS , we just need to pass style as Document for SOAP Binding annotation as below
@SOAPBinding(style=Style.DOCUMENT)
For RPC style it has to be
@SOAPBinding(style=Style.RPC)
Requirement:
Create a web service to find whether given number is prime or not and develop a client which consumes it.
Let’s implement this requirement with below steps
Step 1
Create a new Java maven project in eclipse
Step 2
Create a service endpoint interface
- package com.kb.ws;
- 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 PrimeNumberService {
- @WebMethod
- public boolean isPrimeNumber(int number);
- }
package com.kb.ws; 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 PrimeNumberService { @WebMethod public boolean isPrimeNumber(int number); }
A service endpoint interface (SEI) is a Java interface that declares the methods that a client can invoke on the service.
Client will always rely on SEI to call the web service
@WebService indicates its a service interface
@WebMethod on top of method indicates that specified method will be exposed as a service to client.
we can include multiple methods in the service but need to provide @WebMethod annotation on each method.
We have specified Binding style as Document using @SOAPBinding annotation.
Note
By default message style is considered as Document in JAX-WS hence specifying @SOAPBinding(style=Style.DOCUMENT) is optional for Document style web service development.
Step 3
Create a service endpoint implementation
- package com.kb.ws;
- import javax.jws.WebService;
- @WebService(endpointInterface="com.kb.ws.PrimeNumberService")
- public class PrimeNumberServiceImpl implements PrimeNumberService{
- @Override
- public boolean isPrimeNumber(int number) {
- for(int i=2;i<=number/2;i++){
- if(number % i == 0)
- return false;
- }
- return true;
- }
- }
package com.kb.ws; import javax.jws.WebService; @WebService(endpointInterface="com.kb.ws.PrimeNumberService") public class PrimeNumberServiceImpl implements PrimeNumberService{ @Override public boolean isPrimeNumber(int number) { for(int i=2;i<=number/2;i++){ if(number % i == 0) return false; } return true; } }
Here we have specified SEI using endpointInterface property of @Webervice annotation.
com.kb.ws.PrimeNumberService is defined as the end point interface which should be fully qualified name of the endpoint interface created in Step 2
we have written a logic which will check whether given number is prime number or not and returns true if number is prime and returns false if its non prime number
Step 4
Create the web service Publisher class
- package com.kb.endpoint;
- import javax.xml.ws.Endpoint;
- import com.kb.ws.PrimeNumberServiceImpl;
- public class PrimeNumberPublisher {
- public static void main(String[] args) {
- Endpoint endpoint = Endpoint.create(new PrimeNumberServiceImpl());
- endpoint.publish("http://localhost:8889/ws/primeNumber");
- //Endpoint.publish("http://localhost:8889/ws/primeNumber", new PrimeNumberServiceImpl());
- }
- }
package com.kb.endpoint; import javax.xml.ws.Endpoint; import com.kb.ws.PrimeNumberServiceImpl; public class PrimeNumberPublisher { public static void main(String[] args) { Endpoint endpoint = Endpoint.create(new PrimeNumberServiceImpl()); endpoint.publish("http://localhost:8889/ws/primeNumber"); //Endpoint.publish("http://localhost:8889/ws/primeNumber", new PrimeNumberServiceImpl()); } }
In this class we are calling create method of Endpoint class for creating the endpoint for the given implementation object.
We are also calling publish method of Endpoint class which is used to publish the endpoint
Alternative way of creating and publishing the end point is
Endpoint.publish("http://localhost:8889/ws/primeNumber", new PrimeNumberServiceImpl());
It is better to go with create and publish methods as it gives more control over server configuration.
Note:
An endpoint is either in a published or an unpublished state
Once endpoint is published, it starts accepting incoming requests.
Step 5
Run the endpoint publisher
We will get below error
Wrapper class com.kb.ws.jaxws. isPrimeNumberis not found.
Have you run APT to generate them?
This error is coming only for Document style because ,In Document style,SOAP message body contains a XML document unlike method details in RPC, hence SOAP requires mapping classes for the XML schema so that it can validate the SOAP request and can produce the SOAP response.
How to resolve this error?
We just need to run wsgen command to generate the necessary mapping files.
wsgen command is located in Java_HOME/bin folder
Open command prompt, go to the below path
D:\workspace\WebServices\JAXWSPrimeNumberDocumentStyle\target\classes
Issue the following command:
wsgen -keep -cp . com.kb.ws.PrimeNumberServiceImpl
Note
The classpath specified via -cp should point to the directory that contains the compiled classes, typically the target/classes folder in maven project and bin folder in java project.
Now check the below files are generated in the same path from where we issued the command
Generated source files are as below
IsPrimeNumber.java
- package com.kb.generated;
- 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 = "isPrimeNumber", namespace = "http://ws.kb.com/")
- @XmlAccessorType(XmlAccessType.FIELD)
- @XmlType(name = "isPrimeNumber", namespace = "http://ws.kb.com/")
- public class IsPrimeNumber {
- @XmlElement(name = "arg0", namespace = "")
- private int arg0;
- /**
- *
- * @return
- * returns int
- */
- public int getArg0() {
- return this.arg0;
- }
- /**
- *
- * @param arg0
- * the value for the arg0 property
- */
- public void setArg0(int arg0) {
- this.arg0 = arg0;
- }
- }
package com.kb.generated; 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 = "isPrimeNumber", namespace = "http://ws.kb.com/") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "isPrimeNumber", namespace = "http://ws.kb.com/") public class IsPrimeNumber { @XmlElement(name = "arg0", namespace = "") private int arg0; /** * * @return * returns int */ public int getArg0() { return this.arg0; } /** * * @param arg0 * the value for the arg0 property */ public void setArg0(int arg0) { this.arg0 = arg0; } }
IsPrimeNumberResponse.java
- package com.kb.generated;
- 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 = "isPrimeNumberResponse", namespace = "http://ws.kb.com/")
- @XmlAccessorType(XmlAccessType.FIELD)
- @XmlType(name = "isPrimeNumberResponse", namespace = "http://ws.kb.com/")
- public class IsPrimeNumberResponse {
- @XmlElement(name = "return", namespace = "")
- private boolean _return;
- /**
- *
- * @return
- * returns boolean
- */
- public boolean isReturn() {
- return this._return;
- }
- /**
- *
- * @param _return
- * the value for the _return property
- */
- public void setReturn(boolean _return) {
- this._return = _return;
- }
- }
package com.kb.generated; 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 = "isPrimeNumberResponse", namespace = "http://ws.kb.com/") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "isPrimeNumberResponse", namespace = "http://ws.kb.com/") public class IsPrimeNumberResponse { @XmlElement(name = "return", namespace = "") private boolean _return; /** * * @return * returns boolean */ public boolean isReturn() { return this._return; } /** * * @param _return * the value for the _return property */ public void setReturn(boolean _return) { this._return = _return; } }
Copy these files to our project and adjust the package names in the java files accordingly
Step 6
Run the PrimeNumberPublisher class to publish the web service
Step 7
Access wsdl via the URL just by appending ?wsdl at the end of URL as below
http://localhost:8889/ws/primeNumber?wsdl
We can see below wsdl file response
- <!--
- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e.
- -->
- <!--
- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e.
- -->
- <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://ws.kb.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.kb.com/"name="PrimeNumberServiceImplService">
- <types>
- <xsd:schema>
- <xsd:import namespace="http://ws.kb.com/" schemaLocation="http://localhost:8889/ws/primeNumber?xsd=1"/>
- </xsd:schema>
- </types>
- <message name="isPrimeNumber">
- <part name="parameters" element="tns:isPrimeNumber"/>
- </message>
- <message name="isPrimeNumberResponse">
- <part name="parameters" element="tns:isPrimeNumberResponse"/>
- </message>
- <portType name="PrimeNumberService">
- <operation name="isPrimeNumber">
- <input wsam:Action="http://ws.kb.com/PrimeNumberService/isPrimeNumberRequest" message="tns:isPrimeNumber"/>
- <output wsam:Action="http://ws.kb.com/PrimeNumberService/isPrimeNumberResponse" message="tns:isPrimeNumberResponse"/>
- </operation>
- </portType>
- <binding name="PrimeNumberServiceImplPortBinding" type="tns:PrimeNumberService">
- <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
- <operation name="isPrimeNumber">
- <soap:operation soapAction=""/>
- <input>
- <soap:body use="literal"/>
- </input>
- <output>
- <soap:body use="literal"/>
- </output>
- </operation>
- </binding>
- <service name="PrimeNumberServiceImplService">
- <port name="PrimeNumberServiceImplPort" binding="tns:PrimeNumberServiceImplPortBinding">
- <soap:address location="http://localhost:8889/ws/primeNumber"/>
- </port>
- </service>
- </definitions>
<!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --> <!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --> <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://ws.kb.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.kb.com/"name="PrimeNumberServiceImplService"> <types> <xsd:schema> <xsd:import namespace="http://ws.kb.com/" schemaLocation="http://localhost:8889/ws/primeNumber?xsd=1"/> </xsd:schema> </types> <message name="isPrimeNumber"> <part name="parameters" element="tns:isPrimeNumber"/> </message> <message name="isPrimeNumberResponse"> <part name="parameters" element="tns:isPrimeNumberResponse"/> </message> <portType name="PrimeNumberService"> <operation name="isPrimeNumber"> <input wsam:Action="http://ws.kb.com/PrimeNumberService/isPrimeNumberRequest" message="tns:isPrimeNumber"/> <output wsam:Action="http://ws.kb.com/PrimeNumberService/isPrimeNumberResponse" message="tns:isPrimeNumberResponse"/> </operation> </portType> <binding name="PrimeNumberServiceImplPortBinding" type="tns:PrimeNumberService"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="isPrimeNumber"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="PrimeNumberServiceImplService"> <port name="PrimeNumberServiceImplPort" binding="tns:PrimeNumberServiceImplPortBinding"> <soap:address location="http://localhost:8889/ws/primeNumber"/> </port> </service> </definitions>
Web Service clients
Let’s create web service clients to access the deployed web service
- package com.kb.ws.client;
- import java.net.URL;
- import javax.xml.namespace.QName;
- import javax.xml.ws.Service;
- import com.kb.ws.PrimeNumberService;
- public class PrimeNumberClient {
- public static void main(String[] args) throws Exception {
- URL url = new URL("http://localhost:8889/ws/primeNumber?wsdl");
- QName qname = new QName("http://ws.kb.com/", "PrimeNumberServiceImplService");
- Service service = Service.create(url, qname);
- PrimeNumberService primeNumberService = service.getPort(PrimeNumberService.class);
- System.out.println(primeNumberService.isPrimeNumber(13));
- System.out.println(primeNumberService.isPrimeNumber(14));
- }
- }
package com.kb.ws.client; import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.Service; import com.kb.ws.PrimeNumberService; public class PrimeNumberClient { public static void main(String[] args) throws Exception { URL url = new URL("http://localhost:8889/ws/primeNumber?wsdl"); QName qname = new QName("http://ws.kb.com/", "PrimeNumberServiceImplService"); Service service = Service.create(url, qname); PrimeNumberService primeNumberService = service.getPort(PrimeNumberService.class); System.out.println(primeNumberService.isPrimeNumber(13)); System.out.println(primeNumberService.isPrimeNumber(14)); } }
Under QName, need to pass 2 arguments
1st argument is service URI same as targetNamespace in the wsdl
2nd argument is service name which is PrimeNumberServiceImplService as we can see in the WSDL.
Output
Awesome explanation…Thanks!!
Thank you !!