Saturday, May 15, 2010

Webservices using JAX-WS

Hello All,

We are going to create a simple webservice using JAX-WS.
This requires jdk 1.6, glassfish sever.
This is tested on Windows XP SP2, jdk1.6.0_18, Glassfish-v2ur1

This Webservices fetches information of a person by id.

Please follow the instructions...

• Create a directory structure like this.

Webservice
 |
 |
 -----> PersonFetchService
             |
             |
             -----> work
             |            |
             |            |
             |            -----> personfetch.xsd
             |            |
             |            |
             |            -----> personfetch.xjb
             |            |
             |            |
             |            -----> compile.bat
             |
             |
             -----> PersonFetchApp
                         |
                         |
                         -----> WEB-INF
                                     |
                                     |
                                     -----> web.xml
                                     |
                                     |
                                     -----> classes

• personfetch.xsd

We have to determine the structure of request and response. What we want to send and what we want back, so we now define a xsd for that purpose.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.samplews.com/schema/personfetch" elementFormDefault="qualified" xmlns:tns="http://www.samplews.com/schema/personfetch">
    <xsd:complexType name="PersonFetchRequest">
        <xsd:sequence>
            <xsd:element name="Id" type="xsd:int"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="PersonFetchResponse">
        <xsd:sequence>
            <xsd:element name="Id" type="xsd:int"/>
            <xsd:element name="Name" type="xsd:string"/>
            <xsd:element name="Address" type="tns:Address"/>
            <xsd:element name="PhoneNo" type="xsd:decimal"/>
            <xsd:element name="Email" type="xsd:string"/>
            <xsd:element name="BirthDate" type="xsd:date"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="Address">
        <xsd:sequence>
            <xsd:element name="Line1" type="xsd:string"/>
            <xsd:element name="Line2" type="xsd:string"/>
            <xsd:element name="Line3" type="xsd:string"/>
            <xsd:element name="City" type="xsd:string"/>
            <xsd:element name="Pincode" type="xsd:decimal"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

• personfetch.xjb

The xjb file specifies in which package the generated java classes resides for given targetnamespace of xsd specified in schema location.

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1.0">
    <jaxb:bindings schemaLocation="personfetch.xsd" node="/xsd:schema">
        <jaxb:schemaBindings>
            <jaxb:package name="com.samplews.personfetch"/>
        </jaxb:schemaBindings>
    </jaxb:bindings>
</jaxb:bindings>

• compile.bat

This batch is to compile all java file under specified package.

javac com/samplews/personfetch/*.java
pause

• web.xml

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

• Navigate to "work" folder on command prompt.

• Execute this command.

This command generates java classes according to xsd and configuration of xjb which we will use to pass into and to return from webservice.

xjc personfetch.xsd -b personfetch.xjb -d .

You would get source files generated under "work".

• Create a java file under com --> samplews --> personfetch named "PersonFetchWS.java".

This is the webservice class. You can see the parameter and return type of the the fetchInfo method.

• PersonFetchWS.java

package com.samplews.personfetch;

import javax.jws.*;
import javax.jws.soap.SOAPBinding;
import java.math.BigDecimal;

@WebService(name = "PersonFetchWS", serviceName = "PersonFetchWSService", portName = "PersonFetchWSPort", targetNamespace = "http://www.samplews.com/webservice/personfetch")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)

public class PersonFetchWS {

    public PersonFetchWS() {

    }

    @WebMethod(operationName = "FetchInfo")
    public
    @WebResult(name = "PersonFetchResponse", targetNamespace = "http://www.samplews.com/schema/personfetch")
    PersonFetchResponse fetchInfo(@WebParam(name = "PersonFetchRequest", targetNamespace = "http://www.samplews.com/schema/personfetch")PersonFetchRequest request) {
        PersonFetchResponse response=new PersonFetchResponse();
        response.setId(request.getId());
        response.setName("TestPerson");
        Address address=new Address();
        address.setLine1("Line1");
        address.setLine2("Line2");
        address.setLine3("Line3");
        address.setCity("Mahemdabad");
        address.setPincode(new BigDecimal("387130"));
        response.setAddress(address);
        response.setPhoneNo(new BigDecimal("9999999999"));
        response.setEmail("testperson@testdomain.com");
        return response;
    }

}

• Execute the "compile.bat" to compile all source files.

• Copy the "com" folder and paste it to Webservices --> PersonFetchService --> PersonFetchApp --> WEB-INF --> classes

• Navidate to "PersonFetchService" on command prompt.

• Execute this command.

The command will package all stuff under "PersonFetchService" derectory and create a jar file.

jar cvf PersonFetchApp.war -C PersonFetchApp .

You would get "PersonFetchApp.war" under "PersonFetchService".

• Deploy this war file in glassfish.

When you deploy the war the glassfish internally uses wsgen to create server artifact like wsdl file, java file of request, java file of response, etc.

• Enter this url in browser's address bar.

http://[hostname]:[port]/PersonFetchApp/PersonFetchWSService

• You would see Webservice information.

• To call the webservices use the class.

• CallPersonFetchWS.java

import java.io.*;
import java.net.*;

public class CallPersonFetchWS {

    public static void main(String args[]) throws Exception {
        URL url = new URL("http://[host]:[port]/PersonFetchApp/PersonFetchWSService");
        URLConnection con = url.openConnection();
        con.setDoInput(true);
        con.setDoOutput(true);
        con.setUseCaches(false);
        con.setDefaultUseCaches(false);
        con.setRequestProperty("content-type", "text/xml");
        String request="<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:ns1=\"http://www.samplews.com/schema/personfetch\">"+
        "<soap:Header/>"+
        "<soap:Body>"+
        "<ns1:PersonFetchRequest>"+
        "<ns1:Id>1</ns1:Id>"+
        "</ns1:PersonFetchRequest>"+
        "</soap:Body>"+
        "</soap:Envelope>";
        byte[] filebytes = request.getBytes();
        con.connect();
        OutputStream out = con.getOutputStream();
        try {
            out.write(filebytes);
            out.flush();
        } finally {
            out.close();
        }
        InputStream in = con.getInputStream();
        byte[] inbytes = new byte[in.available()];
        try {
            in.read(inbytes);
        } finally {
            in.close();
        }
        String resStr = new String(inbytes);
        System.out.println(resStr);
    }
}

I think this would help. Please put suggestions if this not helping you, so I can improve this.
Thanks...