Skip navigation

Category Archives: JAX-WS

Hi All,

I cleared SCDJWS 5.0 with over 80% …

I am thinking of preparing a study guide with sample questions for the exam since this exam does not have a dedicated guide.

Lets see if I am able to find out some time !!!

Advertisements

XML-based webservices make use of XML messages for communication. While working with JAX-WS , programmers work with SEI (Service Endpoint Interface) which simplify and hide the details of converting between Java method invocations and their associated XML messages.But if you want to work directly with XML messages you can consider using Dispatch interface. Dispatch client API (javax.xml.ws.Dispatch) is a low level API that requires clients to construct messages or message payloads as XML.
Using Dispatch, the client can send data in either MESSAGE or PAYLOAD mode.

MESSAGE Mode : Using the MESSAGE mode (javax.xml.ws.Service.Mode.MESSAGE), the Dispatch client works directly with the message . The entire SOAP envelope (<soap:Envelope>,<soap:Header>, and <soap:Body>) is provided by the client.

PAYLOAD Mode : Using the PAYLOAD (javax.xml.ws.Service.Mode.PAYLOAD ) mode, the Dispatch client wokrs with the payload of the message . The client is responsible for providing the contents of the . The element is provided by JAX-WS.

The Dispatch client implementations should support following types of objects:

Type of Object

Description

Bindings Supported

javax.xml.transform.Source

Clients can use XML generating and consuming API’s directly

HTTP & SOAP

JAXB Objects

Clients use JAXB generated objects

HTTP & SOAP

javax.xml.soap.SOAPMessage

Clients work with SOAP messsages

SOAP binding in Message mode

javax.activation.DataSource

Clients work with MIME-types messages

HTTP binding in Message mode

Hi All,

Great place to buy stuff : Deals2buy

In this series we will look at using JAX-WS for building Web Services. This series will start with simple web services and then we will go on complex topics. I won’t be dealing with advantages and basics of JAX-WS here.

Building a Web Service (Server-Side) :

We will start with a simple Server side class .

import java.util.HashMap;
import java.util.Map;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public class BookQuoteEndpoint {
	static Map bookPriceMap = new HashMap();

	static {
		bookPriceMap.put("J2EE Web Services","500");
		bookPriceMap.put("SOA using Java Web Service","450");
	}

	@WebMethod
	public String getBookPrice(String bookname) {

		if(bookPriceMap.containsKey(bookname)) {
			return bookPriceMap.get(bookname);
		} else {
			return "Book Not Found";
		}

	}
}

Those who are familiar with JAX-RPC will appreciate the fact that this class looks very simple (thanks to heavy use of Annotations in JAX-WS) .There is no interface to implement , no exceptions to be declared ….
I have declared BookQuoteEndpoint as a Web Service which has its method getBookPrice exposed as a Web Service operation. I get a String as input (name of the boook whose price is to be found) and return back a String which gives the price of the book.

Now we need to deploy this on the server . You can use Tomcat or Glassfish . I used Glassfish for these examples simply because I found it great !

I used the ant file to build this application.I have used the build.xml from the samples which you get here https://jax-ws.dev.java.net/jax-ws-20-fcs/samples/docs/index.html .

To build the server side you need to use apt task. Apt task will process the annotations and generate two source files : GetBookPrice and GetBookPriceResponse . These two classes are the wrappers for input and output parameters of the getBookPrice method.

This is how the ANT task looks like :

    <taskdef name="apt" classname="com.sun.tools.ws.ant.Apt">
        <classpath refid="jaxws.classpath"/>
    </taskdef>

    <target name="build-server-java" depends="setup">
        <apt
                fork="true"
                debug="true"
                verbose="${verbose}"
                destdir="${build.classes.home}"
                sourcedestdir="${build.classes.home}"
                sourcepath="${basedir}/src">
            <classpath>
                <path refid="jaxws.classpath"/>
                <pathelement location="${basedir}/src"/>
            </classpath>
            <option key="r" value="${build.home}"/>
            <source dir="${basedir}">
                <include name="src/**/*.java"/>
            </source>
        </apt>
        <!-- copy handlers descriptor file -->
        <copy todir="${build.classes.home}">
            <fileset dir="${basedir}/src">
                <include name="**/*.xml"/>
            </fileset>
        </copy>
    </target>

We first need to define a new definition to the current project using taskdef. This task is implemented by com.sun.tools.ws.ant.Apt. The jaxws.classpath refers to the jar files of Web service. I am using Sun RI in this tutorial.

Here is the description of the attributes of this task :


destdir                    Location to store the class files.
sourcedestdir           Location to store the source files generated while processing the annotations
sourcepath         	Location of the java files which are to be processed.

The GetBookPrice looks like this :

package com.example.jaxws;

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 = "getBookPrice", namespace = "http://example.com/")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getBookPrice", namespace = "http://example.com/")
public class GetBookPrice {

    @XmlElement(name = "arg0", namespace = "")
    private String arg0;

    /**
     *
     * @return
     *     returns String
     */
    public String getArg0() {
        return this.arg0;
    }

    /**
     *
     * @param arg0
     *     the value for the arg0 property
     */
    public void setArg0(String arg0) {
        this.arg0 = arg0;
    }

}

First thing you would notice here is that the package is com.example.jaxws while the BookQuoteEndpoint had com.example . This class is generated by the APT tool and it generates this package by default. We can of course customize so as to suite our package.

Lets have a look at GetBookPriceResponse class as well.

@XmlRootElement(name = "getBookPriceResponse", namespace = "http://example.com/")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getBookPriceResponse", namespace = "http://example.com/")
public class GetBookPriceResponse {

    @XmlElement(name = "return", namespace = "")
    private String _return;

    /**
     *
     * @return
     *     returns String
     */
    public String getReturn() {
        return this._return;
    }

    /**
     *
     * @param _return
     *     the value for the _return property
     */
    public void setReturn(String _return) {
        this._return = _return;
    }

}

Once you have these classes you just need some configuration files .

Lets see the deployment descriptor first :

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

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<listener>
	<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>
    <servlet>
        <description>JAX-WS endpoint - sample1</description>
        <display-name>sample1</display-name>
        <servlet-name>sample1</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>sample1</servlet-name>
        <url-pattern>/getBookQuote</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
</web-app>

For Glassfish , I had to use one more configuration file called sun-jaxws.xml . It looks like this :

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

<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>
    <endpoint
        name='sample1'
        implementation='com.example.BookQuoteEndpoint'
        url-pattern='/getBookQuote'/>

</endpoints>

This file is kept in the same directory as the deployment descriptor (WEB-INF). You then need to create a war and deploy it in Glassfish. Try accessing the wsdl like this:

http://localhost:8080/jaxwsserver/getBookQuote?wsdl

Wow you have deployed your web service successfully !!!

Creating a Web Service Client :
To generate a client we need to use wsimport task . Either you can use ant task for wsimport or you can use wsimport directly on command prompt.This is how you use wsimport in ant .

    <taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
        <classpath refid="jaxws.classpath"/>
    </taskdef>
    <wsimport
                debug="true"
                verbose="${verbose}"
                keep="true"
                destdir="${build.classes.home}"
                package="com.example"
                wsdl="http://localhost:8080/jaxwsserver/getBookQuote?wsdl">
    </wsimport>

This wsimport task is implemented by com.sun.tools.ws.ant.WsImport .

Let us see various attributes of wsimport task :

keep          Keep generated files
destdir       Specify where to place output generated classes
package       Specifies the target package
wsdl          Location of the wsdl file . You can have wsdl in your machine or you can give the URL  where you can get it

When this task is executed, you have java files are generated in the dest dir . You will see these all files generated :

interface BookQuoteEndpoint
class BookQuoteEndpointService extends Service
class GetBookPrice
class GetBookPriceResponse
class ObjectFactory
package-info.java

Now we will see how we use these classes in our Client application :

package com.example;

public class BookQuoteClient {

	public static void main(String args[]) {
		BookQuoteEndpoint bqe = new BookQuoteEndpointService().getBookQuoteEndpointPort();
		String price = bqe.getBookPrice("J2EE Web Services");
		System.out.println(price);
	}
}

As you can see in the client program we are first creating an instance of BookQuoteEndpointService and getting a port from that instance. The class BookQuoteEndpointService extends a Service . A Service is an abstraction which represents a WSDL service.Calling getPort method on the service gives you a Proxy . Proxies provide access to service endpoint interfaces at runtime without requiring static generation of a stub class.

The Proxy returned is of type BookQuoteEndpoint . On this proxy we call the method getBookPrice with paramters and get the result .

This finishes with the creation of our first Web Service application using JAX-WS.