Monday, February 4, 2013

Develop web service with jaxws


1) download jax-ws jar from either http://jax-ws.java.net or maven respository
2) add JAXWS_HOME to your system env variables
3) key in command
wsgen -version
or
wsimport -version
to verify jax-ws setup is ok

wsgen generates the necessary artifacts required for jax-ws applications when starting from Java code.
wsimport processes an existing WSDL file and generates the required artifacts for developing jax-ws web service applications.

4) start from wsdl

==== define a soap header in a separate xsd file common-schema.xsd ==========

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:common="http://ws.abc.com/common/" attributeFormDefault="unqualified"
elementFormDefault="qualified" targetNamespace="http://ws.abc.com/common/">
<xs:complexType name="reqHeader">
<xs:sequence>
<xs:element name="clientId" type="xs:string" />
<xs:element name="timeStamp" type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="respHeader">
<xs:sequence>
<xs:element name="returnCode" type="common:codeType" />
<xs:element name="returnMessage" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="codeType">
<xs:restriction base="xs:string">
<xs:enumeration value="000" />
<xs:enumeration value="999" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

===============  define demo.wsdl ======================



<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="demoService" targetNamespace="http://ws.abc.com/demows/"
xmlns:common="http://ws.abc.com/common/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:demows="http://ws.abc.com/demows/" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<xs:schema>
<xs:import namespace="http://ws.abc.com/demows/"
schemaLocation="demo-schema.xsd" />
<xs:import namespace="http://ws.abc.com/common/"
schemaLocation="common-schema.xsd" />
</xs:schema>
</wsdl:types>

<wsdl:message name="reqCreate">
<wsdl:part name="parameters" element="demows:createReqParams" />
</wsdl:message>
<wsdl:message name="respCreate">
<wsdl:part name="parameters" element="demows:createRespParams" />
</wsdl:message>


<wsdl:message name="reqGet">
<wsdl:part name="parameters" element="demows:getReqParams" />
</wsdl:message>
<wsdl:message name="respGet">
<wsdl:part name="parameters" element="demows:getRespParams" />
</wsdl:message>

<wsdl:portType name="DemoService">
<wsdl:operation name="create" parameterOrder="parameters">
<wsdl:input message="demows:reqCreate" />
<wsdl:output message="demows:respCreate" />
</wsdl:operation>

<wsdl:operation name="get" parameterOrder="parameters">
<wsdl:input message="demows:reqGet" />
<wsdl:output message="demows:respGet" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="DemoServicePortBinding" type="demows:DemoService">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="create">
<soap:operation soapAction="create" />
<wsdl:input>
<soap:body parts="parameters" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body parts="parameters" use="literal" />
</wsdl:output>
</wsdl:operation>

<wsdl:operation name="get">
<soap:operation soapAction="get" />
<wsdl:input>
<soap:body parts="parameters" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body parts="parameters" use="literal" />
</wsdl:output>
</wsdl:operation>

</wsdl:binding>
<wsdl:service name="DemoService">
<wsdl:port name="DemoServicePort" binding="demows:DemoServicePortBinding">
<soap:address location="http://localhost:8080/demows/demoservice" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>



================ xsd file (demo-schema.xsd) for demo.wsdl   ============

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:common="http://ws.abc.com/common/" xmlns:demows="http://ws.abc.com/demows/"
attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="http://ws.abc.com/demows/">
<xs:import namespace="http://ws.abc.com/common/"
schemaLocation="common-schema.xsd" />
<xs:element name="createReqParams" type="demows:createReqParamsType" />
<xs:element name="createRespParams" type="demows:createRespParamsType" />
<xs:element name="getReqParams" type="demows:getReqParamsType" />
<xs:element name="getRespParams" type="demows:getRespParamsType" />

<xs:complexType name="createReqParamsType">
<xs:sequence>
<xs:element name="header" type="common:reqHeader" />
<xs:element name="prodId" type="xs:string" />
</xs:sequence>
</xs:complexType>

<xs:complexType name="createRespParamsType">
<xs:sequence>
<xs:element name="header" type="common:respHeader" />
<xs:element name="prodId" type="xs:string" />
<xs:element name="prodStatus" type="demows:prodStatus" />
</xs:sequence>
</xs:complexType>

<xs:complexType name="getReqParamsType">
<xs:sequence>
<xs:element name="header" type="common:reqHeader" />
<xs:element name="prodId" type="xs:string" />
</xs:sequence>
</xs:complexType>

<xs:complexType name="getRespParamsType">
<xs:sequence>
<xs:element name="header" type="common:respHeader" />
<xs:element name="prodId" type="xs:string" />
<xs:element name="prodList" type="demows:prodList" />
</xs:sequence>
</xs:complexType>

<xs:complexType name="prodList">
<xs:sequence>
<xs:element name="prodDetail" type="demows:prodDetail"
maxOccurs="unbounded" minOccurs="0" />
</xs:sequence>
</xs:complexType>

<xs:complexType name="prodDetail">
<xs:sequence>
<xs:element name="prodId" type="xs:string" />
<xs:element name="prodName" type="xs:string" />
<xs:element minOccurs="0" name="prodType" type="demows:prodType" />
</xs:sequence>
</xs:complexType>

<xs:simpleType name="prodStatus">
<xs:restriction base="xs:string">
<xs:enumeration value="Pass" />
<xs:enumeration value="Fail" />
<xs:enumeration value="Pending" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="prodType">
<xs:restriction base="xs:string">
<xs:enumeration value="Good" />
<xs:enumeration value="Bad" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

5) use wsimport to generate skeleton stuff

wsimport demo.wsdl -Xnocompile -extension

6) skeleton code:


package com.abc.ws.demows.skeleton;

import java.util.Date;

import javax.jws.WebService;
import javax.xml.ws.Holder;

import com.abc.ws.common.ReqHeader;
import com.abc.ws.common.RespHeader;
import com.abc.ws.demows.CreateReqParamsType;
import com.abc.ws.demows.CreateRespParamsType;
import com.abc.ws.demows.DemoService;
import com.abc.ws.demows.GetReqParamsType;
import com.abc.ws.demows.GetRespParamsType;
import com.abc.ws.demows.ProdStatus;
@WebService( endpointInterface = "com.abc.ws.demows.DemoService" )
public class DemoServiceImpl implements DemoService {

@Override
public void create(CreateReqParamsType parameters,
Holder<CreateRespParamsType> parameters0) {
// print the request data
String prodId = parameters.getProdId();
ReqHeader reqHeader = parameters.getHeader();
String clientId = reqHeader.getClientId();
Date timestamp = reqHeader.getTimeStamp().toGregorianCalendar()
.getTime();

System.out.println("request data: prodId=" + prodId + ",clientId="
+ clientId + ",timestamp=" + timestamp);

// return data
CreateRespParamsType resp = new CreateRespParamsType();
RespHeader respHeader = new RespHeader();
respHeader.setReturnCode("9999");
respHeader.setReturnMessage("OK");
resp.setProdId("PID01");
resp.setHeader(respHeader);
resp.setProdStatus(ProdStatus.PASS);

parameters0.value=resp;
}

@Override
public void get(GetReqParamsType parameters,
Holder<GetRespParamsType> parameters0) {
// TODO Auto-generated method stub

}

}

7) add sun-jaxws.xml to folder WEB-INF\

refer to http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/jaxws/jaxws-war.html

<?xml version="1.0" encoding="UTF-8"?>

<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>

    <endpoint 
        name='demows'
        implementation='com.abc.ws.demows.skeleton.DemoServiceImpl'
        url-pattern='/demoservice'/>
</endpoints>

8) add listener and servlet to web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="demows" version="2.5">

<display-name>demows</display-name>
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>demows</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>demows</servlet-name>
<url-pattern>/demoservice</url-pattern>
</servlet-mapping>
</web-app>

9) after deploy to tomcat, browser url: http://localhost:8080/demows/demoservice








10) stub code to call the web service

package com.abc.ws.demows.stub;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.ws.Holder;
import javax.xml.ws.Service;

import com.abc.ws.common.ReqHeader;
import com.abc.ws.demows.CreateReqParamsType;
import com.abc.ws.demows.CreateRespParamsType;
import com.abc.ws.demows.DemoService;
import com.abc.ws.demows.DemoService_Service;
import com.abc.ws.demows.skeleton.DemoServiceImpl;

public class ClientTest {

public static void main(String[] args)
throws DatatypeConfigurationException, MalformedURLException {

URL wsdlUrl = new URL("http://localhost:8080/wsdemo/demoservice");

/* if not sure the value of namespaceURL and localPart to init QName, take a look the info  on http://localhost:8080/wsdemo/demoservice , for this case,
Service Name:{http://skeleton.demows.ws.abc.com/}DemoServiceImplService
*/
QName serviceName = new QName("http://skeleton.demows.ws.abc.com/",
"DemoServiceImplService");
Service service = Service.create(wsdlUrl, serviceName);

DemoService port = service.getPort(DemoService.class);
CreateReqParamsType reqPara = new CreateReqParamsType();
ReqHeader header = new ReqHeader();
header.setClientId("CID0001");
header.setTimeStamp(getXMLGregorianCalendarNow());
reqPara.setHeader(header);
reqPara.setProdId("PID02");

CreateRespParamsType respPara = new CreateRespParamsType();
Holder<CreateRespParamsType> resp = new Holder<CreateRespParamsType>();
resp.value = respPara;

port.create(reqPara, resp);

System.out.println("response data:" + resp.value.getProdId() + ","
+ resp.value.getHeader().getReturnCode() + ","
+ resp.value.getHeader().getReturnMessage() + ","
+ resp.value.getProdStatus().value());

}

public static XMLGregorianCalendar getXMLGregorianCalendarNow()
throws DatatypeConfigurationException {
GregorianCalendar gregorianCalendar = new GregorianCalendar();
DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
XMLGregorianCalendar now = datatypeFactory
.newXMLGregorianCalendar(gregorianCalendar);
return now;
}
}

test result:

message printed by skeleton:
request data: prodId=PID02,clientId=CID0001,timestamp=Mon Feb 04 12:29:17 SGT 2013

message printed by stub:
response data:PID01,9999,OK,Pass

No comments:

Post a Comment