JAX-WS Basic example – RPC Style
In this article, we will perform below tasks based on our requirement
Create RPC style web service using JAX-WS and expose it with end point
Create java web service client manually
Create java web service client using wsimport
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 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.RPC)
- 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.RPC) 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 RPC using @SOAPBinding annotation.
Read more about RPC and other binding style in SOAP message binding style article
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:8888/ws/primeNumber");
- }
- }
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:8888/ws/primeNumber"); } }
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:8888/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
Now Prime number service is deployed at http://localhost:8888/ws/primeNumber
Step 6
Access wsdl via the URL just by appending ?wsdl at the end of URL as below
http://localhost:8888/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/>
- <message name="isPrimeNumber">
- <part name="arg0" type="xsd:int"/>
- </message>
- <message name="isPrimeNumberResponse">
- <part name="return" type="xsd:boolean"/>
- </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="rpc"/>
- <operation name="isPrimeNumber">
- <soap:operation soapAction=""/>
- <input>
- <soap:body use="literal" namespace="http://ws.kb.com/"/>
- </input>
- <output>
- <soap:body use="literal" namespace="http://ws.kb.com/"/>
- </output>
- </operation>
- </binding>
- <service name="PrimeNumberServiceImplService">
- <port name="PrimeNumberServiceImplPort" binding="tns:PrimeNumberServiceImplPortBinding">
- <soap:address location="http://localhost:8888/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/> <message name="isPrimeNumber"> <part name="arg0" type="xsd:int"/> </message> <message name="isPrimeNumberResponse"> <part name="return" type="xsd:boolean"/> </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="rpc"/> <operation name="isPrimeNumber"> <soap:operation soapAction=""/> <input> <soap:body use="literal" namespace="http://ws.kb.com/"/> </input> <output> <soap:body use="literal" namespace="http://ws.kb.com/"/> </output> </operation> </binding> <service name="PrimeNumberServiceImplService"> <port name="PrimeNumberServiceImplPort" binding="tns:PrimeNumberServiceImplPortBinding"> <soap:address location="http://localhost:8888/ws/primeNumber"/> </port> </service> </definitions>
Web Service clients
Let’s create web service clients to access the deployed web service
We can create the client either manually or we can use wsimport tool to do the same
We will discuss both the options
1. Creating web service client with wsimport tool
Java provides wsimport utility tool which helps in generating the client support code by using the WSDL document.
Its available under JDK_PATH/bin folder.
Let’s use the WSDL file and generate the client files
Open command prompt and issue the below command
wsimport -keep -p client http://localhost:8888/ws/primeNumber?wsdl
-keep option specifies that it has to keep the generated files.
-p allows us to specify the java package name in which the generated files are to be placed.
We have given the package name as “client” so it will keep in client package.
Output of wsimport command
Now client code is generated under the path from where we issued wsimport command
We can see 2 source files and 2 class files generated in my folder
Generated files are as below
PrimeNumberService.java
- package com.kb.ws.client;
- import javax.jws.WebMethod;
- import javax.jws.WebParam;
- import javax.jws.WebResult;
- import javax.jws.WebService;
- import javax.jws.soap.SOAPBinding;
- import javax.xml.ws.Action;
- /**
- * This class was generated by the JAX-WS RI.
- * JAX-WS RI 2.2.9-b130926.1035
- * Generated source version: 2.2
- *
- */
- @WebService(name = "PrimeNumberService", targetNamespace = "http://ws.kb.com/")
- @SOAPBinding(style = SOAPBinding.Style.RPC)
- public interface PrimeNumberService {
- /**
- *
- * @param arg0
- * @return
- * returns boolean
- */
- @WebMethod
- @WebResult(partName = "return")
- @Action(input = "http://ws.kb.com/PrimeNumberService/isPrimeNumberRequest", output = "http://ws.kb.com/PrimeNumberService/isPrimeNumberResponse")
- public boolean isPrimeNumber(
- @WebParam(name = "arg0", partName = "arg0")
- int arg0);
- }
package com.kb.ws.client; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import javax.xml.ws.Action; /** * This class was generated by the JAX-WS RI. * JAX-WS RI 2.2.9-b130926.1035 * Generated source version: 2.2 * */ @WebService(name = "PrimeNumberService", targetNamespace = "http://ws.kb.com/") @SOAPBinding(style = SOAPBinding.Style.RPC) public interface PrimeNumberService { /** * * @param arg0 * @return * returns boolean */ @WebMethod @WebResult(partName = "return") @Action(input = "http://ws.kb.com/PrimeNumberService/isPrimeNumberRequest", output = "http://ws.kb.com/PrimeNumberService/isPrimeNumberResponse") public boolean isPrimeNumber( @WebParam(name = "arg0", partName = "arg0") int arg0); }
PrimeNumberServiceImplService.java
- package com.kb.ws.client;
- import java.net.MalformedURLException;
- import java.net.URL;
- import javax.xml.namespace.QName;
- import javax.xml.ws.Service;
- import javax.xml.ws.WebEndpoint;
- import javax.xml.ws.WebServiceClient;
- import javax.xml.ws.WebServiceException;
- import javax.xml.ws.WebServiceFeature;
- /**
- * This class was generated by the JAX-WS RI.
- * JAX-WS RI 2.2.9-b130926.1035
- * Generated source version: 2.2
- *
- */
- @WebServiceClient(name = "PrimeNumberServiceImplService", targetNamespace = "http://ws.kb.com/", wsdlLocation = "http://localhost:8888/ws/primeNumber?wsdl")
- public class PrimeNumberServiceImplService
- extends Service
- {
- private final static URL PRIMENUMBERSERVICEIMPLSERVICE_WSDL_LOCATION;
- private final static WebServiceException PRIMENUMBERSERVICEIMPLSERVICE_EXCEPTION;
- private final static QName PRIMENUMBERSERVICEIMPLSERVICE_QNAME = new QName("http://ws.kb.com/", "PrimeNumberServiceImplService");
- static {
- URL url = null;
- WebServiceException e = null;
- try {
- url = new URL("http://localhost:8888/ws/primeNumber?wsdl");
- } catch (MalformedURLException ex) {
- e = new WebServiceException(ex);
- }
- PRIMENUMBERSERVICEIMPLSERVICE_WSDL_LOCATION = url;
- PRIMENUMBERSERVICEIMPLSERVICE_EXCEPTION = e;
- }
- public PrimeNumberServiceImplService() {
- super(__getWsdlLocation(), PRIMENUMBERSERVICEIMPLSERVICE_QNAME);
- }
- public PrimeNumberServiceImplService(WebServiceFeature... features) {
- super(__getWsdlLocation(), PRIMENUMBERSERVICEIMPLSERVICE_QNAME, features);
- }
- public PrimeNumberServiceImplService(URL wsdlLocation) {
- super(wsdlLocation, PRIMENUMBERSERVICEIMPLSERVICE_QNAME);
- }
- public PrimeNumberServiceImplService(URL wsdlLocation, WebServiceFeature... features) {
- super(wsdlLocation, PRIMENUMBERSERVICEIMPLSERVICE_QNAME, features);
- }
- public PrimeNumberServiceImplService(URL wsdlLocation, QName serviceName) {
- super(wsdlLocation, serviceName);
- }
- public PrimeNumberServiceImplService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
- super(wsdlLocation, serviceName, features);
- }
- /**
- *
- * @return
- * returns PrimeNumberService
- */
- @WebEndpoint(name = "PrimeNumberServiceImplPort")
- public PrimeNumberService getPrimeNumberServiceImplPort() {
- return super.getPort(new QName("http://ws.kb.com/", "PrimeNumberServiceImplPort"), PrimeNumberService.class);
- }
- /**
- *
- * @param features
- * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
- * @return
- * returns PrimeNumberService
- */
- @WebEndpoint(name = "PrimeNumberServiceImplPort")
- public PrimeNumberService getPrimeNumberServiceImplPort(WebServiceFeature... features) {
- return super.getPort(new QName("http://ws.kb.com/", "PrimeNumberServiceImplPort"), PrimeNumberService.class, features);
- }
- private static URL __getWsdlLocation() {
- if (PRIMENUMBERSERVICEIMPLSERVICE_EXCEPTION!= null) {
- throw PRIMENUMBERSERVICEIMPLSERVICE_EXCEPTION;
- }
- return PRIMENUMBERSERVICEIMPLSERVICE_WSDL_LOCATION;
- }
- }
package com.kb.ws.client; import java.net.MalformedURLException; import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.Service; import javax.xml.ws.WebEndpoint; import javax.xml.ws.WebServiceClient; import javax.xml.ws.WebServiceException; import javax.xml.ws.WebServiceFeature; /** * This class was generated by the JAX-WS RI. * JAX-WS RI 2.2.9-b130926.1035 * Generated source version: 2.2 * */ @WebServiceClient(name = "PrimeNumberServiceImplService", targetNamespace = "http://ws.kb.com/", wsdlLocation = "http://localhost:8888/ws/primeNumber?wsdl") public class PrimeNumberServiceImplService extends Service { private final static URL PRIMENUMBERSERVICEIMPLSERVICE_WSDL_LOCATION; private final static WebServiceException PRIMENUMBERSERVICEIMPLSERVICE_EXCEPTION; private final static QName PRIMENUMBERSERVICEIMPLSERVICE_QNAME = new QName("http://ws.kb.com/", "PrimeNumberServiceImplService"); static { URL url = null; WebServiceException e = null; try { url = new URL("http://localhost:8888/ws/primeNumber?wsdl"); } catch (MalformedURLException ex) { e = new WebServiceException(ex); } PRIMENUMBERSERVICEIMPLSERVICE_WSDL_LOCATION = url; PRIMENUMBERSERVICEIMPLSERVICE_EXCEPTION = e; } public PrimeNumberServiceImplService() { super(__getWsdlLocation(), PRIMENUMBERSERVICEIMPLSERVICE_QNAME); } public PrimeNumberServiceImplService(WebServiceFeature... features) { super(__getWsdlLocation(), PRIMENUMBERSERVICEIMPLSERVICE_QNAME, features); } public PrimeNumberServiceImplService(URL wsdlLocation) { super(wsdlLocation, PRIMENUMBERSERVICEIMPLSERVICE_QNAME); } public PrimeNumberServiceImplService(URL wsdlLocation, WebServiceFeature... features) { super(wsdlLocation, PRIMENUMBERSERVICEIMPLSERVICE_QNAME, features); } public PrimeNumberServiceImplService(URL wsdlLocation, QName serviceName) { super(wsdlLocation, serviceName); } public PrimeNumberServiceImplService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) { super(wsdlLocation, serviceName, features); } /** * * @return * returns PrimeNumberService */ @WebEndpoint(name = "PrimeNumberServiceImplPort") public PrimeNumberService getPrimeNumberServiceImplPort() { return super.getPort(new QName("http://ws.kb.com/", "PrimeNumberServiceImplPort"), PrimeNumberService.class); } /** * * @param features * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values. * @return * returns PrimeNumberService */ @WebEndpoint(name = "PrimeNumberServiceImplPort") public PrimeNumberService getPrimeNumberServiceImplPort(WebServiceFeature... features) { return super.getPort(new QName("http://ws.kb.com/", "PrimeNumberServiceImplPort"), PrimeNumberService.class, features); } private static URL __getWsdlLocation() { if (PRIMENUMBERSERVICEIMPLSERVICE_EXCEPTION!= null) { throw PRIMENUMBERSERVICEIMPLSERVICE_EXCEPTION; } return PRIMENUMBERSERVICEIMPLSERVICE_WSDL_LOCATION; } }
wsimport has generated the interface PrimeNumberService which has the same method as the original method inside PrimeNumberService at server side.
PrimeNumberServiceImplService has a no-argument constructor that will be used to construct the Service object
PrimeNumberServiceImplService has a method getPrimeNumberServiceImplPort () that returns instance of PrimeNumberService on which service methods has to be called.
Let’s create another java project in eclipse for web service client and copy these generated client files
Just change the package inside java files accordingly
Create the client class and call the web service using above generated files
PrimeNumberClient.java
- package com.kb.ws.client;
- public class PrimeNumberClient {
- public static void main(String[] args) {
- PrimeNumberServiceImplService service = new PrimeNumberServiceImplService();
- PrimeNumberService primeNumberService = service.getPrimeNumberServiceImplPort();
- System.out.println(primeNumberService.isPrimeNumber(13));
- System.out.println(primeNumberService.isPrimeNumber(14));
- }
- }
package com.kb.ws.client; public class PrimeNumberClient { public static void main(String[] args) { PrimeNumberServiceImplService service = new PrimeNumberServiceImplService(); PrimeNumberService primeNumberService = service.getPrimeNumberServiceImplPort(); System.out.println(primeNumberService.isPrimeNumber(13)); System.out.println(primeNumberService.isPrimeNumber(14)); } }
Output
2. Creating web service client manually without wsimport tool
- package com.kb.ws.client;
- import java.net.MalformedURLException;
- import java.net.URL;
- import javax.xml.namespace.QName;
- import javax.xml.ws.Service;
- public class PrimeNumberManualClient {
- public static void main(String[] args) throws Exception {
- URL url = new URL("http://localhost:8888/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.MalformedURLException; import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.Service; public class PrimeNumberManualClient { public static void main(String[] args) throws Exception { URL url = new URL("http://localhost:8888/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
You can replace the test in
for(int i=2;i<number/2;i++)
by
for(int i=2;i<=Math.sqrt(number);i++)