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

JAXWSPrimeNumberDocumentServiceProjStructure


Step 2

Create a service endpoint interface

  1. package com.kb.ws;
  2.  
  3. import javax.jws.WebMethod;
  4. import javax.jws.WebService;
  5. import javax.jws.soap.SOAPBinding;
  6. import javax.jws.soap.SOAPBinding.Style;
  7.  
  8. @WebService
  9. @SOAPBinding(style=Style.DOCUMENT)
  10. public interface PrimeNumberService {
  11.    
  12.     @WebMethod
  13.     public boolean isPrimeNumber(int number);
  14. }
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

  1. package com.kb.ws;
  2.  
  3. import javax.jws.WebService;
  4.  
  5. @WebService(endpointInterface="com.kb.ws.PrimeNumberService")
  6. public class PrimeNumberServiceImpl implements PrimeNumberService{
  7.  
  8.     @Override
  9.     public boolean isPrimeNumber(int number) {
  10.         for(int i=2;i<=number/2;i++){
  11.             if(number % i == 0)
  12.                 return false;
  13.         }
  14.         return true;
  15.     }
  16.  
  17. }
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

  1. package com.kb.endpoint;
  2.  
  3. import javax.xml.ws.Endpoint;
  4.  
  5. import com.kb.ws.PrimeNumberServiceImpl;
  6.  
  7. public class PrimeNumberPublisher {
  8.     public static void main(String[] args) {
  9.         Endpoint endpoint = Endpoint.create(new PrimeNumberServiceImpl());
  10.         endpoint.publish("http://localhost:8889/ws/primeNumber");
  11.         //Endpoint.publish("http://localhost:8889/ws/primeNumber", new PrimeNumberServiceImpl());
  12.     }
  13.  
  14. }
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

jax-ws-document-prime-number-wsgen-cmd-output

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

jax-ws-document-prime-number-wsimport-cmd-output-files

Generated source files are as below

IsPrimeNumber.java

  1. package com.kb.generated;
  2.  
  3. import javax.xml.bind.annotation.XmlAccessType;
  4. import javax.xml.bind.annotation.XmlAccessorType;
  5. import javax.xml.bind.annotation.XmlElement;
  6. import javax.xml.bind.annotation.XmlRootElement;
  7. import javax.xml.bind.annotation.XmlType;
  8.  
  9. @XmlRootElement(name = "isPrimeNumber", namespace = "http://ws.kb.com/")
  10. @XmlAccessorType(XmlAccessType.FIELD)
  11. @XmlType(name = "isPrimeNumber", namespace = "http://ws.kb.com/")
  12. public class IsPrimeNumber {
  13.  
  14.     @XmlElement(name = "arg0", namespace = "")
  15.     private int arg0;
  16.  
  17.     /**
  18.      *
  19.      * @return
  20.      *     returns int
  21.      */
  22.     public int getArg0() {
  23.         return this.arg0;
  24.     }
  25.  
  26.     /**
  27.      *
  28.      * @param arg0
  29.      *     the value for the arg0 property
  30.      */
  31.     public void setArg0(int arg0) {
  32.         this.arg0 = arg0;
  33.     }
  34.  
  35. }
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

  1. package com.kb.generated;
  2.  
  3. import javax.xml.bind.annotation.XmlAccessType;
  4. import javax.xml.bind.annotation.XmlAccessorType;
  5. import javax.xml.bind.annotation.XmlElement;
  6. import javax.xml.bind.annotation.XmlRootElement;
  7. import javax.xml.bind.annotation.XmlType;
  8.  
  9. @XmlRootElement(name = "isPrimeNumberResponse", namespace = "http://ws.kb.com/")
  10. @XmlAccessorType(XmlAccessType.FIELD)
  11. @XmlType(name = "isPrimeNumberResponse", namespace = "http://ws.kb.com/")
  12. public class IsPrimeNumberResponse {
  13.  
  14.     @XmlElement(name = "return", namespace = "")
  15.     private boolean _return;
  16.  
  17.     /**
  18.      *
  19.      * @return
  20.      *     returns boolean
  21.      */
  22.     public boolean isReturn() {
  23.         return this._return;
  24.     }
  25.  
  26.     /**
  27.      *
  28.      * @param _return
  29.      *     the value for the _return property
  30.      */
  31.     public void setReturn(boolean _return) {
  32.         this._return = _return;
  33.     }
  34.  
  35. }
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

  1. <!--
  2.  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.
  3. -->
  4. <!--
  5.  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.
  6. -->
  7. <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">
  8. <types>
  9. <xsd:schema>
  10. <xsd:import namespace="http://ws.kb.com/" schemaLocation="http://localhost:8889/ws/primeNumber?xsd=1"/>
  11. </xsd:schema>
  12. </types>
  13. <message name="isPrimeNumber">
  14. <part name="parameters" element="tns:isPrimeNumber"/>
  15. </message>
  16. <message name="isPrimeNumberResponse">
  17. <part name="parameters" element="tns:isPrimeNumberResponse"/>
  18. </message>
  19. <portType name="PrimeNumberService">
  20. <operation name="isPrimeNumber">
  21. <input wsam:Action="http://ws.kb.com/PrimeNumberService/isPrimeNumberRequest" message="tns:isPrimeNumber"/>
  22. <output wsam:Action="http://ws.kb.com/PrimeNumberService/isPrimeNumberResponse" message="tns:isPrimeNumberResponse"/>
  23. </operation>
  24. </portType>
  25. <binding name="PrimeNumberServiceImplPortBinding" type="tns:PrimeNumberService">
  26. <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
  27. <operation name="isPrimeNumber">
  28. <soap:operation soapAction=""/>
  29. <input>
  30. <soap:body use="literal"/>
  31. </input>
  32. <output>
  33. <soap:body use="literal"/>
  34. </output>
  35. </operation>
  36. </binding>
  37. <service name="PrimeNumberServiceImplService">
  38. <port name="PrimeNumberServiceImplPort" binding="tns:PrimeNumberServiceImplPortBinding">
  39. <soap:address location="http://localhost:8889/ws/primeNumber"/>
  40. </port>
  41. </service>
  42. </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

  1. package com.kb.ws.client;
  2.  
  3. import java.net.URL;
  4.  
  5. import javax.xml.namespace.QName;
  6. import javax.xml.ws.Service;
  7.  
  8. import com.kb.ws.PrimeNumberService;
  9.  
  10. public class PrimeNumberClient {
  11.     public static void main(String[] args) throws Exception {
  12.         URL url = new URL("http://localhost:8889/ws/primeNumber?wsdl");
  13.  
  14.         QName qname = new QName("http://ws.kb.com/", "PrimeNumberServiceImplService");
  15.  
  16.         Service service = Service.create(url, qname);
  17.  
  18.         PrimeNumberService primeNumberService = service.getPort(PrimeNumberService.class);
  19.  
  20.         System.out.println(primeNumberService.isPrimeNumber(13));
  21.         System.out.println(primeNumberService.isPrimeNumber(14));
  22.     }
  23.  
  24. }
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

Download this project JAXWSPrimeNumberDocumentStyle.zip

About the Author

Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on