Skip navigation

Hi Everyone !

A post after such a long time …Busy with project 😦

I am learning Flex with Java and working on the integration issues . Will update soon with the issues and solutions !

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 !!!

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.

Hi All,

In this blog we will see how to use Request/Reply model in JMS.

On a broad level,JMS supports two messaging models : Point-to-Point (PTP) and Publish-Subscribe. These are easier to create and there are many examples available.Here we will see a third kind of model called as Request-Reply model. This is an “overlay” model since it is implemented on the top of other two models.

Let us see how to create this model in JMS : We will use PTP model as the basic model. While sending the message, the Producer/Sender can specify the Reply To queue . Using this Reply To queue the Receiver/Consumer can send a reply back to the Producer.

To create a Reply To queue in the producer :

Destination replyQueue = session.createTemporaryQueue();
message.setJMSReplyTo(replyQueue);

To get the Reply To queue in the consumer :

Destination replyDestination = message.getJMSReplyTo();

Now let us see the full code for Producer :

public void sendMessage(String name) throws JustJavaRuntimeException {
	try {
		Connection connection = null;
		Session session = null;
		Destination destination = null;
		MessageProducer messageProducer = null;
		connectionFactory = (ConnectionFactory) ctx.lookup(connectionFactoryName);
		connection = connectionFactory.createConnection();
		session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		destination =(Destination) ctx.lookup(requestQueueName);
		messageProducer = session.createProducer(destination);
		TextMessage message = session.createTextMessage(name);

		//Create Reply To Queue
		connection.start();
		Destination replyQueue = session.createTemporaryQueue();
		message.setJMSReplyTo(replyQueue);
		replyConsumer = session.createConsumer(replyQueue);
		replyConsumer.setMessageListener(new ResponseListener());
		messageProducer.send(message, javax.jms.DeliveryMode.PERSISTENT,   javax.jms.Message.DEFAULT_PRIORITY, 1800000);
		System.out.println("++++++++++++++++++++++++++++++++++++++++++");
		System.out.println("Message sent to Bean");
		System.out.println("ReplyQueue name is : "+replyQueue.toString());
		System.out.println("++++++++++++++++++++++++++++++++++++++++++");

		synchronized (this) {
		try {
		    wait(5000);
		} catch (InterruptedException e) {
		    throw new JustJavaRuntimeException(e);
		}
	}

	messageProducer.close();
	session.close();
	connection.close();

	} catch (JMSException je) {
		throw new JustJavaRuntimeException(je);
	} catch (NamingException ne) {
		throw new JustJavaRuntimeException(ne);
	}
}

One thing you might notice here :

replyConsumer.setMessageListener(new ResponseListener());

Well replyConsumer is a MessageConsumer which is assigned a message listener.This is for listening back the reply we get from the original Consumer.

Few things which are necessary for building Request/Reply model using JMS are :

//Create Reply To Queue
connection.start();
.....
synchronized (this) {
try {
    wait(5000);
} catch (InterruptedException e) {
    throw new JustJavaRuntimeException(e);
}

Well you need to do connection.start() ; This starts a connection’s delivery of incoming messages.

Also we are usiing wait(timeout) here . We need to wait since otherwise the connection would close after sending the message to the original Consumer.We don’t want connection to close till we receive a message from the Consumer back.So I have kept a delay here.

We can also use the MessageConsumer’s receive() method for synchronous receive.

Here is the code for ResponseListener :

class ResponseQueueListener implements MessageListener {
	public void onMessage(Message m) {
		try {
 			if (m instanceof TextMessage) {
				TextMessage replyMessage = (TextMessage) m;
				System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++");
				System.out.println("Received reply ResponseQueueListener");
				System.out.println("\tTime:       " + System.currentTimeMillis() + " ms");
				System.out.println("\tMessage ID: " + replyMessage.getJMSMessageID());
				System.out.println("\tCorrel. ID: " + replyMessage.getJMSCorrelationID());
				System.out.println("\tReply to:   " + replyMessage.getJMSReplyTo());
				System.out.println("\tContents:   " + replyMessage.getText());
				System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++");
			}
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
}

Now let us see the code for Consumer. I have used MessageDrivenBean as Consumer.

@MessageDriven(name = "AsyncMDBean", activationConfig = {
	@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
	@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/RequestQueue")

})
public class AsyncMDBean implements MessageListener {

	private Session session;
	Context ctx;

	public AsyncMDBean() {
 	   	try {
			ctx = new InitialContext();
		} catch (NamingException e) {
			throw new JustJavaRuntimeException(e);
		}
	}

	public void onMessage(Message message) {
		String text = null;
		try {

            	if (message instanceof TextMessage) {

			TextMessage textMessage = (TextMessage) message;
			text = textMessage.getText();
			System.out.println("****************************************************");
			System.out.println("Received message in AsyncMDBean. Name: "+text);
			System.out.println("****************************************************");

			//Send the reply
			Destination replyDestination = message.getJMSReplyTo();
			Connection connection = null;
			ConnectionFactory connectionFactory = (ConnectionFactory) ctx.lookup("ConnectionFactory");
			connection = connectionFactory.createConnection();
			session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			MessageProducer replyProducer = session.createProducer(replyDestination);
			TextMessage replyMessage = session.createTextMessage();
			replyMessage.setText("ABCD");
			replyProducer.send(replyMessage);

			System.out.println("****************************************************");
			System.out.println("Sent reply");
			System.out.println("\tTime:       " + System.currentTimeMillis() + " ms");
			System.out.println("\tMessage ID: " + replyMessage.getJMSMessageID());
			System.out.println("\tCorrel. ID: " + replyMessage.getJMSCorrelationID());
			System.out.println("\tReply to:   " + replyMessage.getJMSReplyTo());
			System.out.println("\tContents:   " + replyMessage.getText());
			System.out.println("****************************************************");

        	} else {
		       	System.err.println("Expected a Text Message");
        	}

        	System.out.println("*******************************************");
        	System.out.println("Leaving AsyncMDBean. Name: "+text );
        	System.out.println("*******************************************");
        	} catch (Throwable t) {
            		t.printStackTrace();
        	}
	}
}

Well thats it !!!

Please let me how did you find this code ….. I have deployed it successfully on JBoss 4.2.3 … There were some issues on Glassfish.