Chapter 2. Building Clients for SOAP Web-Services

In this chapter, we will cover:

  • Setting up a Web-Service client development environment within Eclipse

  • Setting up a Web-Service client development environment using Maven

  • Creating a Web-Service client on HTTP transport

  • Creating a Web-Service client on JMS transport

  • Creating a Web-Service client on E-mail transport

  • Creating a Web-Service client on XMPP transport

  • Creating a Web-Service client using XPath expression

  • Creating a Web-Service client for WS-Addressing endpoint

  • Transforming a Web-Service message using XSLT

Introduction

Using Java API, such as SAAJ, client-side SOAP messages can be generated and transmitted to/from a Web-Service. However, it requires an extra amount of coding and knowledge about SOAP messages.

The package org.springframework.ws.client.core contains the core functionality of the client-side API, which facilitates calling the server-side Web-Service.

APIs in this package provide template classes like WebServiceTemplate that simplifies the use of Web-Services. Using these templates, you will be able to create a Web-Service client over various transport protocols (HTTP, JMS, e-mail, XMPP, and so on) and send/receive XML messages as well as marshal objects to XML before sending them. Spring also provides classes, such as StringSource and Result, which simplify passing and retrieving XML messages while using WebServiceTemplate.

In this chapter, the first two recipes explain how to set up the environment for calling a Web-Service client using Eclipse and Maven.

Then we will discuss the usage of WebServiceTemplate to create a Web-Service client over various transport protocols (HTTP, JMS, e-mail, XMPP, and so on). In addition to this, the recipe Setting up a Web-Service client using an XPath expression explains how to retrieve data from an XML message. Finally, in the last recipe, Transforming a Web-Service message using XSLT, how to convert the XML messages into different formats between the client and server is presented. To set up a Web-Service server, some recipes from Chapter 1, Building SOAP Web-Services, are used and a separate client project is created that calls the server-side Web-Service.

Setting up a Web-Service client development environment within Eclipse

A Web-Service client in the simplest form is a Java class that calls a server-side Web-Service. In this recipe, setting up the environment to call a server-side Web-Service is presented. Here, a client-side Java class calls a Web-Service on the server in two forms. The first one is a Java class that calls a Web-Service in the main method of the class. The second one uses the JUnit test class to call the server-side Web-Service.

Getting ready

This recipe is similar to the recipe Using Maven for building and running a Spring-WS, discussed in Chapter 1,Building SOAP Web-Services.

  1. Download and install the Eclipse IDE for Java EE developers Helios.

  2. In this recipe, the project's name is LiveRestaurant_R-2.1 (for server-side Web-Service), with the following Maven dependencies:

    • spring-ws-core-2.0.1.RELEASE.jar

    • jdom-1.0.jar

    • log4j-1.2.9.jar

    • jaxen-1.1.jarb

    • xalan-2.7.0.jar

  3. The LiveRestaurant_R-2.1-Client (for the client side) has the following Maven dependencies:

    • spring-ws-core-2.0.1.RELEASE.jar

    • jdom-1.0.jar

    • log4j-1.2.9.jar

    • jaxen-1.1.jar

    • xalan-2.7.0.jar

    • junit-4.7.jar

  4. Run the following Maven command to be able to import the client projects into Eclipse (for the client side):

mvn eclipse:eclipse -Declipse.projectNameTemplate="LiveRestaurant_R-2.1-Client"

How to do it...

This recipe uses the recipe Handling the incoming XML messages using JDOM, discussed in Chapter 1, Building SOAP Web-Services, as the server-side project.

  1. Run a Java class that calls a Web-Service in the main method.

  2. Import LiveRestaurant_R-2.1-Client into the Eclipse workspace by going to File | Import | General | Existing projects into workspace | LiveRestaurant_R-2..1-Client.

  3. Go to the folder LiveRestaurant_R-2.1 in the command prompt and run the server using the following command:

    mvn clean package tomcat:run
    
    
  4. Select the class OrderServiceClient in the folder src/main/java from the package com.packtpub.liverestaurant.client and select Run As | Java Application.

    The following is the console output on running the Java class on the client side:

    Received response ....
    <tns:placeOrderResponse xmlns:tns=".."> <tns:refNumber>order-John_Smith_9999</tns:refNumber>
    </tns:placeOrderResponse>
    for request...
    <tns:placeOrderRequest xmlns:tns="...">
    <tns:order>
    <tns:refNumber>9999</tns:refNumber>
    <tns:customer>
    .......
    </tns:customer>
    <tns:dateSubmitted>2008-09-29T05:49:45</tns:dateSubmitted>
    <tns:orderDate>2014-09-19T03:18:33</tns:orderDate>
    <tns:items>
    <tns:type>Snacks</tns:type>
    <tns:name>Pitza</tns:name>
    <tns:quantity>2</tns:quantity>
    </tns:items>
    </tns:order>
    </tns:placeOrderRequest>....
    
    
  5. Run a JUnit test case using Eclipse.

  6. Select the class OrderServiceClientTest in the folder src/test/java from the package com.packtpub.liverestaurant.client and select Run As | Junit Test.

    The following is the console output on running the JUnit test case (you can click on the JUnit tab, adjacent to the Console tab, to see whether the test case has succeeded or not):

Received response ..
<tns:placeOrderResponse xmlns:tns="...">
<tns:refNumber>order-John_Smith_9999</tns:refNumber>
</tns:placeOrderResponse>..
......
<tns:placeOrderRequest xmlns:tns=".....">
<tns:order>
<tns:refNumber>9999</tns:refNumber>
<tns:customer>
......
</tns:customer>
<tns:dateSubmitted>2008-09-29T05:49:45</tns:dateSubmitted>
<tns:orderDate>2014-09-19T03:18:33</tns:orderDate>
<tns:items>
<tns:type>Snacks</tns:type>
<tns:name>Pitza</tns:name>
<tns:quantity>2</tns:quantity>
</tns:items>
</tns:order>
</tns:placeOrderRequest>

Note

To pass parameters or customize the settings for a test, select the test unit class, Run As | Run Configuration |, and double-click on JUnit on the left pane.

Then you will be able to customize the passed parameters or the settings and run the client.

How it works...

When a Java class that calls a Web-Service in the main method is run, Eclipse runs the following command internally using the following Java class path:

java -classpath com.packtpub.liverestaurant.client.OrderServiceClient

When a JUnit test case is run, Eclipse runs a test case using the JUnit framework by internally calling the following command:

java -classpath com.packtpub.liverestaurant.client.OrderServiceClientTest

See also

The recipes Using Maven for building and running a Spring-WS project and Handling the incoming XML messages using JDOM, discussed in Chapter 1,

The recipe Creating a Web-Service client on HTTP transport, discussed in this chapter.

Setting up a Web-Service client development environment using Maven

Maven supports running the main method of a class using command prompt as well as a JUnit test case.

In this recipe, setting up a Maven environment to call a client-side Web-Service is explained. Here, a client-side Java code calls a Web-Service on the server in two forms. The first one is a Java class that calls a Web-Service in the main method of the class. The second one uses JUnit to call a server-side Web-Service.

Getting ready

In this recipe, the project's name is LiveRestaurant_R-2.2 (for a server-side Web-Service) with the following Maven dependencies:

  • spring-ws-core-2.0.1.RELEASE.jar

  • log4j-1.2.9.jar

The following are the Maven dependencies for LiveRestaurant_R-2.2-Client (for the client-side Web-Service):

  • spring-ws-core-2.0.1.RELEASE.jar

  • junit-4.7.jar

How to do it...

This recipe uses the recipe Handling the incoming XML messages using DOM, discussed in Chapter 1, Building SOAP Web-Services, as the server-side project.

  1. Run a Java class that calls a Web-Service in the main method.

  2. Go to the folder LiveRestaurant_R-2.2 in the command prompt and run the server using the following command:

    mvn clean package tomcat:run
    
    
  3. Go to the folder LiveRestaurant_R-2.2-Client and run the following command:

    mvn clean package exec:java
    
    
    • The following is the output when the Maven command is run on the client side:

    Received response ....
    <placeOrderResponse xmlns="...">
    <refNumber>order-John_Smith_9999</refNumber>
    </placeOrderResponse>....
    <tns:placeOrderRequest xmlns:tns="...">
    <tns:order>
    <tns:refNumber>9999</tns:refNumber>
    <tns:customer>
    .....
    </tns:customer>
    <tns:dateSubmitted>2008-09-29T05:49:45</tns:dateSubmitted>
    <tns:orderDate>2014-09-19T03:18:33</tns:orderDate>
    <tns:items>
    <tns:type>Snacks</tns:type>
    <tns:name>Pitza</tns:name>
    <tns:quantity>2</tns:quantity>
    </tns:items>
    </tns:order>
    </tns:placeOrderRequest>
    
    
  4. Run a JUnit test case using Maven.

  5. Go to the folder LiveRestaurant_R-2.2 from the command prompt and run the server using the following command:

    mvn clean package tomcat:run
    
    
  6. Go to the folder LiveRestaurant_R-2.2-Client and run the following command:

mvn clean package

  • Here is the output after running the JUnit test case using Maven on the client side:

Received response ...
<placeOrderResponse xmlns="...">
<refNumber>order-John_Smith_9999</refNumber>
</placeOrderResponse>...
for request ...
<tns:placeOrderRequest xmlns:tns="...">
<tns:order>
<tns:refNumber>9999</tns:refNumber>
<tns:customer>
.....
</tns:customer>
<tns:dateSubmitted>2008-09-29T05:49:45</tns:dateSubmitted>
<tns:orderDate>2014-09-19T03:18:33</tns:orderDate>
<tns:items>
<tns:type>Snacks</tns:type>
<tns:name>Pitza</tns:name>
<tns:quantity>2</tns:quantity>
</tns:items>
</tns:order>
</tns:placeOrderRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>]
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.702 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

How it works...

Run a Java class that calls a Web-Service in the main method, exec-maven-plugin, set in the pom.xml file. The Java class tells Maven to run mainClass of OrderServiceClient:

<build>
<finalName>LiveRestaurant_Client</finalName>
<plugins>
.......
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.packtpub.liverestaurant.client.OrderServiceClient</mainClass>
</configuration>
</plugin>
</plugins>
</build>

Maven runs the following command internally using the project class path:

java -classpath com.packtpub.liverestaurant.client.OrderServiceClient

To set up and run a JUnit test case in Maven, the test class OrderServiceClientTest should be included in the folder src/test/java and the test class name should end with Test (OrderServiceClientTest). The command mvn clean package runs all the test cases in the src/test/java folder (internal Maven calls):

java -classpath ...;junit.jar.. junit.textui.TestRunner com.packtpub.liverestaurant.client.OrderServiceClientTest ) .

See also

The recipes Using Maven for building and running a Spring-WS project and Handling the incoming XML messages using JDOM, discussed in Chapter 1,Building SOAP Web-Services.

The recipe Creating a Web-Service client on HTTP transport, discussed in this chapter.

Creating a Web-Service client on HTTP transport

In this recipe, WebServiceTemplate is used to send/receive simple XML messages from the client side over the HTTP transport.

Getting ready

In this recipe, the project's name is LiveRestaurant_R-2.3 (for server-side Web-Service) with the following Maven dependencies:

  • spring-ws-core-2.0.1.RELEASE.jar

  • log4j-1.2.9.jar

The following are the Maven dependencies for LiveRestaurant_R-2.3-Client (for the client-side Web-Service):

  • spring-ws-core-2.0.1.RELEASE.jar

  • junit-4.7.jar

How to do it...

This recipe uses the recipe Setting up an endpoint by annotating the payload-root, discussed in Chapter 1, Building SOAP Web-Services, as the server-side project. Here is how you set up the client side:

  1. Create a class that calls the Web-Service server using WebServiceTemplate in src/test.

  2. Configure WebServiceTemplate in the applicationContext.xml file.

  3. From the folder Liverestaurant_R-2.3, run the following command:

    mvn clean package tomcat:run
    
    
  4. Open a new command window to Liverestaurant_R-2.3-Client and run the following command:

mvn clean package

  • The following is the client-side output:

Received response ....
<tns:placeOrderResponse xmlns:tns="...">
<tns:refNumber>order-John_Smith_1234</tns:refNumber>
</tns:placeOrderResponse>...
<tns:placeOrderRequest xmlns:tns="....">
<tns:order>
<tns:refNumber>9999</tns:refNumber>
<tns:customer>
......
</tns:customer>
<tns:dateSubmitted>2008-09-29T05:49:45</tns:dateSubmitted>
<tns:orderDate>2014-09-19T03:18:33</tns:orderDate>
<tns:items>
<tns:type>Snacks</tns:type>
<tns:name>Pitza</tns:name>
<tns:quantity>2</tns:quantity>
</tns:items>
</tns:order>
</tns:placeOrderRequest>
.....
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.749 sec
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

How it works...

Liverestaurant_R-2.3 is a server-side project that reuses the recipe Setting up an endpoint by annotating the payload-root, discussed in Chapter 1,Building SOAP Web-Services.

The applicationContext.xml file of the configured client WebServiceTemplate (id="webServiceTemplate") is used for sending and receiving XML messages. The instance of this bean can be fetched from the client-side program to send and receive XML messages.

messageFactory is an instance of SaajSoapMessageFactory, which is referenced inside WebServiceTemplate. messageFactory is used to create a SOAP packet from the XML messages. The default service URI is the URI that WebServiceTemplate uses by default to send/receive all requests/responses:

<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory" />
<property name="defaultUri" value="http://localhost:8080/LiveRestaurant/spring-ws/OrderService" />
</bean>

OrderServiceClientTest.java is a simple JUnit test case that is used to fetch and initialize WebServiceTemplate from applicationContext.xml in the method setUpBeforeClass() (marked by @BeforeClass). In the methods testCancelOrderRequest and testPlaceOrderRequest (marked by @Test), WebServiceTemplate sends a simple XML message (created by a StringSource object from an existing input XML file) and receives a response from the server wrapped inside the Result object:

private static WebServiceTemplate wsTemplate = null;
private static InputStream isPlace;
private static InputStream isCancel;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
wsTemplate = (WebServiceTemplate) appContext.getBean("webServiceTemplate");
isPlace = new OrderServiceClientTest().getClass().getResourceAsStream("placeOrderRequest.xml");
isCancel = new OrderServiceClientTest().getClass().getResourceAsStream("cancelOrderRequest.xml");
}
@Test
public final void testPlaceOrderRequest() throws Exception {
Result result = invokeWS(isPlace);
Assert.assertTrue(result.toString().indexOf("placeOrderResponse")>0);
}
@Test
public final void testCancelOrderRequest() throws Exception {
Result result = invokeWS(isCancel);
Assert.assertTrue(result.toString().indexOf("cancelOrderResponse")>0);
}
private static Result invokeWS(InputStream is) {
StreamSource source = new StreamSource(is);
StringResult result = new StringResult();
wsTemplate.sendSourceAndReceiveToResult(source, result);
return result;
}

See also

The recipe Setting up an endpoint by annotating the payload-root, discussed in Chapter 1, Building SOAP Web-Services and the recipe Setting up a Web-Service client development environment using Maven, discussed in this chapter.

Creating a Web-Service client on JMS transport

JMS (Java message Service) was introduced in 1999 by Sun Microsystems as part of Java 2, J2EE. The systems that use JMS can communicate synchronously or asynchronously and are based on point-to-point and publish-subscribe models. Spring Web-Services provide features to set up a Web-Service over the JMS protocol that is built upon the JMS functionality in the Spring framework. Spring Web-Service over JMS protocol provides the following communication features:

  • The client and server could be disconnected and can be connected only when sending/receiving messages

  • The client doesn't need to wait until the server replies (in case the server needs a lot of time to process, for example, while doing complex mathematical calculations)

  • JMS provides features that guarantee the delivery of messages between the client and server

In this recipe, WebServiceTemplate is used to send/receive simple XML messages on the client side over JMS transport. A JUnit test case class is used to set up as on server side and send and receive messages using WebServiceTemplate.

Getting ready

In this recipe, the project's name is LiveRestaurant_R-2.4, with the following Maven dependencies:

  • spring-ws-core-2.0.1.RELEASE.jar

  • spring-ws-support-2.0.1.RELEASE.jar

  • spring-test-3.0.5.RELEASE.jar

  • spring-jms-3.0.5.RELEASE.jar

  • junit-4.7.jar

  • xmlunit-1.1.jar

  • log4j-1.2.9.jar

  • jms-1.1.jar

  • activemq-core-4.1.1.jar

How to do it...

This recipe uses the recipe Setting up a Web-Service on JMS transport, discussed in Chapter 1, Building SOAP Web-Services, as a server-side project.

  1. Create a JUnit test class that calls the Web-Service server using WebServiceTemplate.

  2. Configure WebServiceTemplate in applicationContext to send messages over the JMS protocol.

  3. Run the command mvn clean package. You will see the following as output:

Received response ..
<tns:placeOrderResponse xmlns:tns="...">
<tns:refNumber>order-John_Smith_1234</tns:refNumber>
</tns:placeOrderResponse>....
<tns:placeOrderRequest xmlns:tns="...">
<tns:order>
<tns:refNumber>9999</tns:refNumber>
<tns:customer>
.....
</tns:customer>
<tns:dateSubmitted>2008-09-29T05:49:45</tns:dateSubmitted>
<tns:orderDate>2014-09-19T03:18:33</tns:orderDate>
<tns:items>
<tns:type>Snacks</tns:type>
<tns:name>Pitza</tns:name>
<tns:quantity>2</tns:quantity>
</tns:items>
</tns:order>
</tns:placeOrderRequest>

How it works...

In this project, we set up a Web-Service server, over JMS transport, using a JUnit class. The server uses PayloadEndpoint to receive the XML request message and returns a simple XML message as the response (the server is already described in the recipe Setting up a Web-Service on JMS transport, discussed in Chapter 1,Building SOAP Web-Services).

The applicationContext.xml file of the configured client WebServiceTemplate (id="webServiceTemplate") is used for sending and receiving XML messages. The instance of this bean can be fetched from the client-side program to send and receive XML messages. messageFactory is an instance of SaajSoapMessageFactory, referenced inside WebServiceTemplate. messageFactory is used to create a SOAP packet from the XML messages. The default service URI is the JMS URI that WebServiceTemplate uses by default to send/receive all requests/responses. JmsMessageSender, configured inside WebServiceTemplate, is used to send JMS messages. To use the JmsMessageSender, the defaultUri or JMS URI should contain the jms: prefix and a destination name. Some examples of JMS URI are jms:SomeQueue, jms:SomeTopic?priority=3&deliveryMode=NON_PERSISTENT, jms:RequestQueue?replyToName=ResponseName, and so on. By default, the JmsMessageSender sends JMS BytesMessage, but this can be overridden to use TextMessages by using the messageType parameter on the JMS URI. For example, jms:Queue?messageType=TEXT_MESSAGE.

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.jms.JmsMessageSender">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
</property>
<property name="defaultUri" value="jms:RequestQueue?deliveryMode=NON_PERSISTENT"/>
</bean>

JmsTransportWebServiceIntegrationTest.java is a JUnit test case that fetches and injects WebServiceTemplate from the applicationContext.xml file (marked by @ContextConfiguration("applicationContext.xml")). In the method testSendReceive() (marked by @Test), WebServiceTemplate sends a simple XML message (created by a StringSource object from a simple input string) and receives a response from the server wrapped inside the Result object. In the method testSendReceive() (marked by @Test), sending and receiving of messages is similar to the HTTP client and uses WebServiceTemplate.sendSourceAndReceiveToResult to send/receive messages:

@Test
public void testSendReceive() throws Exception {
InputStream is = new JmsTransportWebServiceIntegrationTest().getClass().getResourceAsStream("placeOrderRequest.xml");
StreamSource source = new StreamSource(is);
StringResult result = new StringResult();
webServiceTemplate.sendSourceAndReceiveToResult(source, result);
XMLAssert.assertXMLEqual("Invalid content received", expectedResponseContent, result.toString());
}

See also

The recipe Setting up a Web-Service on JMS transport, discussed in Chapter 1,Building SOAPWeb-Services.

Unit testing a Web-Service using Spring Junit

Creating a Web-Service client on E-mail transport

In this recipe, WebServiceTemplate is used to send/receive simple XML messages on the client side, over E-mail transport. The Setting up a Web-Service on E-mail transport recipe from Chapter 1, Building SOAP Web-Services, is used to set up a Web-Service. A JUnit test case class is used to set up a Web-Service on the server side and messages are sent/received using WebServiceTemplate.

Getting ready

In this recipe, the project's name is LiveRestaurant_R-2.5, with the following Maven dependencies:

  • spring-ws-core-2.0.1.RELEASE.jar

  • spring-ws-support-2.0.1.RELEASE.jar

  • spring-test-3.0.5.RELEASE.jar

  • mail-1.4.1.jar

  • mock-javamail-1.6.jar

  • junit-4.7.jar

  • xmlunit-1.1.jar

How to do it...

This recipe uses the recipe Setting up a Web-Service on E-mail transport, discussed in Chapter 1, Building SOAP Web-Services, as the server-side project.

  1. Create a test class that calls the Web-Service server using WebServiceTemplate.

  2. Configure WebServiceTemplate in applicationContext to send messages over the e-mail protocol.

  3. Run the command mvn clean package. The following is the output of this command:

Received response
<tns:placeOrderResponse xmlns:tns="...">
<tns:refNumber>order-John_Smith_1234</tns:refNumber>
</tns:placeOrderResponse>....
<tns:placeOrderRequest xmlns:tns="...">
<tns:order>
<tns:refNumber>9999</tns:refNumber>
<tns:customer>
.....
</tns:customer>
<tns:dateSubmitted>2008-09-29T05:49:45</tns:dateSubmitted>
<tns:orderDate>2014-09-19T03:18:33</tns:orderDate>
<tns:items>
<tns:type>Snacks</tns:type>
<tns:name>Pitza</tns:name>
<tns:quantity>2</tns:quantity>
</tns:items>
</tns:order>
</tns:placeOrderRequest>

How it works...

This project sets up a Web-Service server over the E-mail transport, using a JUnit class. This class uses Spring JUnit that loads the application context, sets up the server first, and then runs the client unit test to verify that it functions as expected. The server is already explained in the recipe Setting up a Web-Service on E-mail transport, discussed in Chapter 1,Building SOAP Web-Services.

The applicationContext.xml file of the configured client WebServiceTemplate (id="webServiceTemplate") is used for sending and receiving XML messages. The instance of this bean can be fetched from the client-side program to send and receive XML messages. messageFactory is an instance of SaajSoapMessageFactory, referenced inside WebServiceTemplate. messageFactory is used to create a SOAP packet from XML messages. transportURI is a URI used by WebServiceTemplate and indicates the server to use for sending requests. storeURI is a URI, configured inside WebServiceTemplate, and indicates the server to poll for responses (typically, a POP3 or IMAP server). The default URI is the e-mail address URI that WebServiceTemplate uses by default to send/receive all requests/responses:

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.mail.MailMessageSender">
<property name="from" value="[email protected]"/>
<property name="transportUri" value="smtp://smtp.packtpubtest.com"/>
<property name="storeUri" value="imap://[email protected]/INBOX"/>
<property name="receiveSleepTime" value="1500"/>
<property name="session" ref="session"/>
</bean>
</property>
<property name="defaultUri" value="mailto:[email protected]"/>
</bean>
<bean id="session" class="javax.mail.Session" factory-method="getInstance">
<constructor-arg>
<props/>
</constructor-arg>
</bean>

MailTransportWebServiceIntegrationTest.java is a JUnit test case that fetches and injects WebServiceTemplate from applicationContext.xml (marked by @ContextConfiguration("applicationContext.xml")). In the method testWebServiceOnMailTransport()(marked by @Test), WebServiceTemplate sends a simple XML message (created by a StringSource object from an input XML file) and receives a response from the server wrapped inside the Result object.

@Test
public void testWebServiceOnMailTransport() throws Exception {
InputStream is = new MailTransportWebServiceIntegrationTest().getClass().getResourceAsStream("placeOrderRequest.xml");
StreamSource source = new StreamSource(is);
StringResult result = new StringResult();
webServiceTemplate.sendSourceAndReceiveToResult(source, result);
applicationContext.close();
XMLAssert.assertXMLEqual("Invalid content received", expectedResponseContent, result.toString());
}

See also..

The recipe Setting up a Web-Service on E-mail transport, discussed in Chapter 1,Building SOAP Web-Services.

Unit testing a Web-Service using Spring Junit

Setting up a Web-Service on XMPP transport

XMPP (The Extensible Messaging and Presence Protocol) is an open and decentralized XML routing technology on which systems can send XMPP messages to each other. The XMPP network consists of XMPP servers, clients, and services. Each system using XMPP is recognized by a unique ID known as the Jabber ID (JID) . XMPP servers publish XMPP services to offer connected to a client remote service.

In this recipe, WebServiceTemplate is used to send/receive simple XML messages on the client side over XMPP transport. The recipe Setting up a Web-Service on XMPP transport from Chapter 1, Building SOAP Web-Services, is used to set up a Web-Service. A JUnit test case class is used to set up a Web-Service on the server side and send and receive messages using WebServiceTemplate.

Getting ready

In this recipe, the project's name is LiveRestaurant_R-2.6, with the following Maven dependencies:

  • spring-ws-core-2.0.1.RELEASE.jar

  • spring-ws-support-2.0.1.RELEASE.jar

  • spring-test-3.0.5.RELEASE.jar

  • junit-4.7.jar

  • xmlunit-1.1.jar

  • smack-3.1.0.jar

How to do it...

  1. This recipe uses the recipe Setting up a Web-Service on XMPP transport, discussed in Chapter 1, Building SOAP Web-Services, as the server-side project.

  2. Create a test class that calls the Web-Service server using WebServiceTemplate.

  3. Configure WebServiceTemplate in applicationContext to send messages over the XMPP protocol.

  4. Run the command mvn clean package. You will see the following output:

Received response ..
<tns:placeOrderResponse xmlns:tns="...">
<tns:refNumber>order-John_Smith_1234</tns:refNumber>
</tns:placeOrderResponse>....
<tns:placeOrderRequest xmlns:tns="...">
<tns:order>
<tns:refNumber>9999</tns:refNumber>
<tns:customer>
.....
</tns:customer>
<tns:dateSubmitted>2008-09-29T05:49:45</tns:dateSubmitted>
<tns:orderDate>2014-09-19T03:18:33</tns:orderDate>
<tns:items>
<tns:type>Snacks</tns:type>
<tns:name>Pitza</tns:name>
<tns:quantity>2</tns:quantity>
</tns:items>
</tns:order>
</tns:placeOrderRequest>

How it works...

This project sets up a Web-Service server over the XMPP transport using a JUnit class. The server is already explained in the recipe Setting up a Web-Service on e-mail transport, discussed in Chapter 1,Building SOAP Web-Services.

The applicationContext.xml file of the configured client WebServiceTemplate (id="webServiceTemplate") is used for sending and receiving XML messages. The instance of this bean can be fetched from the client-side program to send and receive XML messages. messageFactory is an instance of SaajSoapMessageFactory, referenced inside WebServiceTemplate. messageFactory is used to create a SOAP packet from XML messages. WebServiceTemplate uses XmppMessageSender to send messages to the server. The default URI is a XMPP address URI that WebServiceTemplate uses by default to send/receive all requests/responses:

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.xmpp.XmppMessageSender">
<property name="connection" ref="connection"/>
</bean>
</property>
<property name="defaultUri" value="xmpp:[email protected]"/>
</bean>

XMPPTransportWebServiceIntegrationTest.java is a JUnit test case that fetches and injects WebServiceTemplate from applicationContext.xml (marked by @ContextConfiguration("applicationContext.xml")). In the method testWebServiceOnXMPPTransport()(marked by @Test), WebServiceTemplate sends an XML message (created by a StringSource object from a simple input XML file ) and receives a response from the server wrapped inside the Result object.

@Autowired
private GenericApplicationContext applicationContext;
@Test
public void testWebServiceOnXMPPTransport() throws Exception {
StringResult result = new StringResult();
StringSource sc=new StringSource(requestContent);
webServiceTemplate.sendSourceAndReceiveToResult(sc, result);
XMLAssert.assertXMLEqual("Invalid content received", requestContent, result.toString());
applicationContext.close();
}

See also

The recipe Setting up a Web-Service on XMPP transport, discussed in Chapter 1,Building SOAP Web-Services.

Unit testing a Web-Service using Spring JUnit

Creating a Web-Service client using XPath expressions

Using XPath in Java programming is one of the standard ways of extracting data from XML messages. However, it mixes the XPath address of XML nodes/attributes (that might eventually turn out to be very long) with Java code.

Spring provides a feature to extract these addresses from Java and shift them into the Spring configuration file. In this recipe, the Setting up an endpoint by annotating the payload-root recipe from Chapter 1, Building SOAP Web-Services, is used to set up a Web-Service server.

Getting ready

In this recipe, the project's name is LiveRestaurant_R-2.7 (for the server-side Web-Service), with the following Maven dependencies:

  • spring-ws-core-2.0.1.RELEASE.jar

  • log4j-1.2.9.jar

The following are the Maven dependencies for LiveRestaurant_R-2.7-Client (for the client-side Web-Service):

  • spring-ws-core-2.0.1.RELEASE.jar

  • junit-4.7.jar

  • log4j-1.2.9.jar

How to do it...

This recipe uses the Setting up an endpoint by annotating the payload-root recipe discussed in Chapter 1, Building SOAP Web-Services, as the server-side project.

  1. Configure the XPath expression inside applicationContext.xml.

  2. Configure WebServiceTemplate in applicationContext to send messages over the HTTP protocol, as described in the recipe Creating a Web-Service client on HTTP transport.

  3. Create a test class that calls the Web-Service server using WebServiceTemplate and uses the XPath expression in Java code to extract the desired values.

  4. From the folder Liverestaurant_R-2.7, run the command mvn clean package tomcat:run.

  5. Open a new command window to Liverestaurant_R-2.7-Client and run the following command:

mvn clean package.

  • The following is the output of the client-side code:

--Request
<tns:placeOrderRequest xmlns:tns="http://www.packtpub.com/liverestaurant/OrderService/schema">
<tns:order>
<tns:refNumber>9999</tns:refNumber>
<tns:customer>
<tns:addressPrimary>
<tns:doorNo>808</tns:doorNo>
<tns:building>W8</tns:building>
<tns:street>St two</tns:street>
<tns:city>NY</tns:city>
<tns:country>US</tns:country>
<tns:phoneMobile>0018884488</tns:phoneMobile>
<tns:phoneLandLine>0017773366</tns:phoneLandLine>
<tns:email>[email protected]</tns:email>
</tns:addressPrimary>
<tns:addressSecondary>
<tns:doorNo>409</tns:doorNo>
<tns:building>W2</tns:building>
<tns:street>St one</tns:street>
<tns:city>NY</tns:city>
<tns:country>US</tns:country>
<tns:phoneMobile>0018882244</tns:phoneMobile>
<tns:phoneLandLine>0019991122</tns:phoneLandLine>
<tns:email>[email protected]</tns:email>
</tns:addressSecondary>
<tns:name>
<tns:fName>John</tns:fName>
<tns:mName>Paul</tns:mName>
<tns:lName>Smith</tns:lName>
</tns:name>
</tns:customer>
<tns:dateSubmitted>2008-09-29T05:49:45</tns:dateSubmitted>
<tns:orderDate>2014-09-19T03:18:33</tns:orderDate>
<tns:items>
<tns:type>Snacks</tns:type>
<tns:name>Pitza</tns:name>
<tns:quantity>2</tns:quantity>
</tns:items>
</tns:order>
</tns:placeOrderRequest>
<!--Received response-->
<tns:placeOrderResponse xmlns:tns="...">
<tns:refNumber>order-John_Smith_1234</tns:refNumber></tns:placeOrderResponse>
...Request
<tns:cancelOrderRequest xmlns:tns="http://www.packtpub.com/liverestaurant/OrderService/schema">
<tns:refNumber>9999</tns:refNumber>
</tns:cancelOrderRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>]
...Received response..
<tns:cancelOrderResponse xmlns:tns="http://www.packtpub.com/liverestaurant/OrderService/schema">
<tns:cancelled>true</tns:cancelled></tns:cancelOrderResponse>

How it works...

Setting up the client and server and using WebserviceTemplate are done in the same way as we did in the recipe Creating a Web-Service client on HTTP transport. xpathExpPlace and xpathExpCancel are configured in the client applicationContext.xml and it creates an instance of XPathExpressionFactoryBean that gets a property of expression as the XPath of the required data and namespaces of the XML messages:

<bean id="xpathExpCancel"
class="org.springframework.xml.xpath.XPathExpressionFactoryBean">
<property name="expression" value="/tns:cancelOrderResponse/tns:cancelled" />
<property name="namespaces">
<props>
<prop key="tns">http://www.packtpub.com/liverestaurant/OrderService/schema</prop>
</props>
</property>
</bean>
<bean id="xpathExpPlace"
class="org.springframework.xml.xpath.XPathExpressionFactoryBean">
<property name="expression" value="/tns:placeOrderResponse/tns:refNumber" />
<property name="namespaces">
<props>
<prop key="tns">http://www.packtpub.com/liverestaurant/OrderService/schema</prop>
</props>
</property>
</bean>

In the class OrderServiceClientTest, an instance of XPathExpressionFactoryBean can be extracted from applicationContext. String message = xpathExp.evaluateAsString(result.getNode()) returns the required data using an XPath expression:

@Test
public final void testPlaceOrderRequest() {
DOMResult result=invokeWS(isPlace);
String message = xpathExpPlace.evaluateAsString(result.getNode());
Assert.assertTrue(message.contains("Smith"));
}
@Test
public final void testCancelOrderRequest() {
DOMResult result= invokeWS(isCancel);
Boolean cancelled = xpathExpCancel.evaluateAsBoolean(result.getNode());
Assert.assertTrue(cancelled);
}

See also

The recipe Setting up an endpoint using an XPath expression, discussed in Chapter 1,Building SOAP Web-Services.

The recipe Creating a Web-Service client on HTTP transport, discussed in this chapter.

Unit testing a Web-Service using Spring JUnit.

Creating a Web-Service client for a WS-Addressing endpoint

As described in the recipe Setting up a transport-neutral WS-Addressing endpoint, discussed in Chapter 1, Building SOAP Web-Services, WS-Addressing is an alternative way for routing. Instead of including the routing data within the body of the SOAP messages, WS-Addressing separates the routing data from the messages and includes it with the SOAP headers. Here is a sample of the WS-Addressing style of a SOAP message, sent from the client side:

<SOAP-ENV:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:To>server_uri</wsa:To>
<wsa:Action>action_uri</wsa:Action>
<wsa:From>client_address </wsa:From>
<wsa:ReplyTo>client_address</wsa:ReplyTo>
<wsa:FaultTo>admen_uri </wsa:FaultTo>
<wsa:MessageID>..</wsa:MessageID>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<tns:placeOrderRequest>....</tns:placeOrderReques>
</SOAP-ENV:Body></SOAP-ENV:Envelope>]

While using WS-Addressing, the client or server can access more features when compared to the other methods (including routing data within a message). For example, here the client side can set ReplyTo to its own and FaultTo to the admin endpoint address. Then the server sends successful messages to the client and fault messages to the admin address.

Spring-WS supports client-side WS-Addressing as well as on the server side. To create WS-Addressing headers for the client side, org.springframework.ws.soap.addressing.client.ActionCallback can be used. This callback keeps the Action header as a parameter. It also uses the WS-Addressing version and a To header.

In this recipe, the Setting up a transport-neutral WS-Addressing endpoint recipe, discussed in Chapter 1, Building SOAP Web-Services, is used to set up a WS-Addressing Web-Service. A client application is used here to call the server and return the response object.

Getting ready

In this recipe, the project's name is LiveRestaurant_R-2.8 (for server-side Web-Service), with the following Maven dependencies:

  • spring-ws-core-2.0.1.RELEASE.jar

  • log4j-1.2.9.jar

The following are the Maven dependencies for LiveRestaurant_R-2.8-Client (for the client-side Web-Service):

  • spring-ws-core-2.0.1.RELEASE.jar

  • junit-4.7.jar

  • log4j-1.2.9.jar

How to do it...

This recipe uses the recipe Setting up a transport-neutral WS-Addressing endpoint, discussed in Chapter 1, Building SOAP Web-Services, as the server-side project. Creating a client for WS-Addressing is done in the same way as described in the recipe Creating a Web-Service client on HTTP transport, without using WebServiceTemplate. To add a WS-Addressing header on the client side, the method sendSourceAndReceiveToResult of WebServiceTemplate gets an ActionCallBack instance.

  1. From the folder LiveRestaurant_R-2.8, run the following command:

    mvn clean package tomcat:run
    
    
  2. Open a new command window to LiveRestaurant_R-2.8-Client and run the following command:

mvn clean package

  • The following is the client-side output:

Received response [<SOAP-ENV:Envelope xmlns:SOAP-ENV="..../">
<SOAP-ENV:Header xmlns:wsa="...">
<wsa:To SOAP-ENV:mustUnderstand="1">....</wsa:To><wsa:Action>http://www.packtpub.com/OrderService/CanOrdReqResponse</wsa:Action>
<wsa:MessageID>....</wsa:MessageID>
<wsa:RelatesTo>...</wsa:RelatesTo>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<tns:cancelOrderResponse xmlns:tns="http://www.packtpub.com/liverestaurant/OrderService/schema">
<tns:cancelled>true</tns:cancelled></tns:cancelOrderResponse>
</SOAP-ENV:Body></SOAP-ENV:Envelope>]
for request ...
<SOAP-ENV:Envelope xmlns:SOAP
-ENV=".."><SOAP-ENV:Header xmlns:wsa="..">
<wsa:To SOAP-ENV:mustUnderstand="1">http://www.packtpub.com/liverestaurant/OrderService/schema</wsa:To>
<wsa:To SOAP-ENV:mustUnderstand="1">http://www.packtpub.com/liverestaurant/OrderService/schema</wsa:To>
<wsa:Action>http://www.packtpub.com/OrderService/CanOrdReq</wsa:Action>
<wsa:MessageID>..</wsa:MessageID>
</SOAP-ENV:Header><SOAP-ENV:Body/>
</SOAP-ENV:Envelope>]
<?xml version="1.0" encoding="UTF-8"?>
<tns:cancelOrderResponse xmlns:tns="http://www.packtpub.com/liverestaurant/OrderService/schema">
<tns:cancelled>true</tns:cancelled></tns:cancelOrderResponse>

How it works...

The Liverestaurant_R-2.8 project is a server-side Web-Service that supports the WS-Addressing endpoint.

The applicationContext.xml file of the configured client WebServiceTemplate (id="webServiceTemplate") is used for sending and receiving XML messages, as described in the recipe Creating a Web-Service client on HTTP transport, except for the implementation of the Java class that used WebServiceTemplate.

WS-Addressing client passes an instance of ActionCallBack to the method sendSourceAndReceiveToResult of WebServiceTemplate. Using ActionCallBack, the client adds a custom header that contains the Action URI, for example, http://www.packtpub.com/OrderService/OrdReq and the To URI, for example, http://www.packtpub.com/liverestaurant/OrderService/schema.

@Test
public final void testPlaceOrderRequest() throws URISyntaxException {
invokeWS(isPlace,"http://www.packtpub.com/OrderService/OrdReq");
}
@Test
public final void testCancelOrderRequest() throws URISyntaxException {
invokeWS(isCancel,"http://www.packtpub.com/OrderService/CanOrdReq");
}
private static Result invokeWS(InputStream is,String action) throws URISyntaxException {
StreamSource source = new StreamSource(is);
StringResult result = new StringResult();
wsTemplate.sendSourceAndReceiveToResult(source, new ActionCallback(new URI(action),new Addressing10(),new URI("http://www.packtpub.com/liverestaurant/OrderService/schema")),
result);
return result;
}

Using this header, the server side will be able to find the method in the endpoint (using the @Action annotation).

See also

The recipe Setting up a transport-neutral WS-Addressing endpoint, discussed in Chapter 1,Building SOAP Web-Services.

The recipe Creating a Web-Service client on HTTP transport, discussed in this chapter.

Unit testing a Web-Service using Spring JUnit

Transforming a Web-Service message using XSLT

Eventually, clients of a Web-Service may use different versions of XML messages and the requirement is to use the same Web-Service on the server side.

Spring Web-Services provide PayloadTransformingInterceptor. This endpoint interceptor uses XSLT stylesheets and is useful when you need multiple versions of a Web-Service. Using this interceptor, you can transform the old format of the message to a newer one.

In this recipe, the Setting up a simple endpoint mapping for the Web-Service recipe from Chapter 1, Building SOAP Web-Services, is used to set up a Web-Service and the client application here calls the server and returns the response message.

Getting ready

In this recipe, the project's name is LiveRestaurant_R-2.9 (for a server-side web service), with the following Maven dependencies:

  • spring-ws-core-2.0.1.RELEASE.jar

  • log4j-1.2.9.jar

The following are the Maven dependencies for LiveRestaurant_R-2.9-Client (for the client-side Web-Service):

  • spring-ws-core-2.0.1.RELEASE.jar

  • junit-4.7.jar

  • log4j-1.2.9.jar

How to do it...

This recipe uses the Setting up a simple endpoint mapping for the Web-Service recipe, discussed in Chapter 1, Building SOAP Web-Services, as a server-side project. The client side is the same as discussed in the recipe Creating a Web-Service client on HTTP transport, except for the XSLT files and their configuration in the server-side application context file:

  1. Create the XSLT files(oldResponse.xslt, oldRequest.xslt).

  2. Modify the file spring-ws-servlet.xml in LiveRestaurant_R-2.9 to include the XSLT files

  3. From the folder Liverestaurant_R-2.9, run the following command:

    mvn clean package tomcat:run
    
    
  4. Open a new command window to Liverestaurant_R-2.9-Client and run the following command:

mvn clean package

  • The following is the client-side output:

Received response...
<ns:OrderResponse xmlns:ns="http://www.packtpub.com/LiveRestaurant/OrderService/schema" message="Order Accepted!"/>...
for request ....
<OrderRequest xmlns="http://www.packtpub.com/LiveRestaurant/OrderService/schema" message="This is a sample Order Message"/>

  • The following is the server-side output:

actual request ..
<ns:OrderRequest xmlns:ns="...">
<ns:message>This is a sample Order Message</ns:message></ns:OrderRequest>
actual response = <ns:OrderResponse xmlns:ns="..">
<ns:message>Order Accepted!</ns:message></ns:OrderResponse>

How it works...

The server side is the same as that described in the recipe Setting up a simple endpoint mapping for the Web-Service from Chapter 1, Building SOAP Web-Services. On the client side, WebServiceTemplate and OrderServiceClientTest.java are the same as those described in the recipe Creating a Web-Service client on HTTP transport.

The only difference is the server application context file. The transformingInterceptor bean in spring-servlet.xml uses oldRequests.xslt and oldResponse.xslt to convert the old request XML message to the server's newer version and vice versa, respectively:

. <bean class="org.springframework.ws.server.endpoint.mapping.SimpleMethodEndpointMapping">
<property name="endpoints">
<ref bean="OrderServiceEndpoint" />
</property>
<property name="methodPrefix" value="handle"></property>
<property name="interceptors">
<list>
<bean
class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor">
<property name="logRequest" value="true" />
<property name="logResponse" value="true" />
</bean>
<bean id="transformingInterceptor"
class="org.springframework.ws.server.endpoint.interceptor.PayloadTransformingInterceptor">
<property name="requestXslt" value="/WEB-INF/oldRequests.xslt" />
<property name="responseXslt" value="/WEB-INF/oldResponse.xslt" />
</bean>
</list>
</property>
</bean>

See also

The recipe Setting up a simple endpoint mapping for the Web-Service, discussed in Chapter 1,Building SOAP Web-Services.

Unit testing a Web-Service using Spring JUnit.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset