jws

JAX-WS Client timeout Example

1. Introduction

In this post, we feature a comprehensive Example on JAX-WS Client timeout. Java API for XML Web Services (JAX-WS) specification was introduced in 2005. There are several tools that implement JAX-WS specification: JDK (since version 6), Apache CXFApache AxisJBossWSIBM WebSphere, and Oracle Weblogic. There are two common timeouts in client-server architecture:

  • Read timeout –  the timeout while waiting for the data from the server. Specifically, if the server fails to send the last byte within the read timeout setting, a read timeout error will be raised.
  • Connection timeout –  the timeout while making the initial connection between the client and server.

In this example, I will demonstrate how to set up these two timeout properties for JAX-WS clients.

2. Technologies Used

The example code in this article was built and run using:

  • Java 1.8.101
  • Maven 3.3.9
  • Apache CXF 3.2.6
  • Eclipse Oxygen
  • Logback 1.2.3

3. Maven Project

In this step, I will create a Maven project which generates Java stubs from a calculator service.

3.1 Dependencies

The project contains several dependencies, the most important one is the JAX-WS JDK runtime library.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>jcg.zheng.demo</groupId>
	<artifactId>jax-ws-client-timeout</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<!-- https://mvnrepository.com/artifact/com.sun.xml.ws/jaxws-rt -->
		<dependency>
			<groupId>com.sun.xml.ws</groupId>
			<artifactId>jaxws-rt</artifactId>
			<version>2.1.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/junit/junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
		<!-- logback -->
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-access</artifactId>
			<version>1.2.3</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.2.3</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-core</artifactId>
			<version>1.2.3</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>jaxws-maven-plugin</artifactId>
				<version>2.5</version>
				<executions>
					<execution>
						<id>jaxws-calculator_wsdl</id>
						<goals>
							<goal>wsimport</goal>
						</goals>
						<configuration>
							<wsdlUrls>
								<wsdlUrl>http://www.dneonline.com/calculator.asmx?wsdl</wsdlUrl>
							</wsdlUrls>
							<keep>true</keep>
							<packageName>jcg.zheng.demo.jaxws.client.calculator</packageName>
							<sourceDestDir>${basedir}/src/main/jaxws</sourceDestDir>
						</configuration>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.cxf</groupId>
				<artifactId>cxf-codegen-plugin</artifactId>
				<version>3.2.6</version>
				<executions>
					<execution>
						<id>generate-sources</id>
						<phase>generate-sources</phase>
						<configuration>
							<sourceRoot>${basedir}/src/main/cxf</sourceRoot>
							<wsdlOptions>
								<wsdlOption>
									<wsdl>http://www.dneonline.com/calculator.asmx?wsdl</wsdl>
								</wsdlOption>
							</wsdlOptions>
						</configuration>
						<goals>
							<goal>wsdl2java</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

4. Generated Java Stubs

Execute mvn clean install to generate the Java stubs from http://www.dneonline.com/calculator.asmx?wsdl.

We should not modify the generated files.

4.1 Generated Files from wsimport

Use wsimport from jaxws-maven-plugin to generate files at /src/main/jaxws.

List of Java Files Generated

C:\gitworkspace\jax-ws-client-timeout\src\main\jaxws\jcg\zheng\demo\jaxws\client\calculator>dir
 Volume in drive C is OSDisk
 Volume Serial Number is 3A10-C6D4

 Directory of C:\gitworkspace\jax-ws-client-timeout\src\main\jaxws\jcg\zheng\demo\jaxws\client\calculator

09/08/2018  08:31 AM    <DIR>          .
09/08/2018  08:31 AM    <DIR>          ..
09/08/2018  08:31 AM             1,622 Add.java
09/08/2018  08:31 AM             1,367 AddResponse.java
09/08/2018  08:31 AM             2,976 Calculator.java
09/08/2018  08:31 AM             3,806 CalculatorSoap.java
09/08/2018  08:31 AM             1,628 Divide.java
09/08/2018  08:31 AM             1,403 DivideResponse.java
09/08/2018  08:31 AM             1,632 Multiply.java
09/08/2018  08:31 AM             1,427 MultiplyResponse.java
09/08/2018  08:31 AM             2,290 ObjectFactory.java
09/08/2018  08:31 AM               190 package-info.java
09/08/2018  08:31 AM             1,632 Subtract.java
09/08/2018  08:31 AM             1,427 SubtractResponse.java
              12 File(s)         21,400 bytes
               2 Dir(s)  22,013,812,736 bytes free

4.2 Generated Files from wsdl2java

Use wsdl2java from cxf-codegen-plugin to generate stubs at /src/main/cxf.

List of Java Files Generated

C:\gitworkspace\jax-ws-client-timeout\src\main\cxf\org\tempuri>dir
 Volume in drive C is OSDisk
 Volume Serial Number is 3A10-C6D4

 Directory of C:\gitworkspace\jax-ws-client-timeout\src\main\cxf\org\tempuri

09/09/2018  08:39 AM    <DIR>          .
09/09/2018  08:39 AM    <DIR>          ..
09/09/2018  08:39 AM             1,625 Add.java
09/09/2018  08:39 AM             1,367 AddResponse.java
09/09/2018  08:39 AM             3,629 Calculator.java
09/09/2018  08:39 AM             3,178 CalculatorSoap.java
09/09/2018  08:39 AM             1,631 Divide.java
09/09/2018  08:39 AM             1,403 DivideResponse.java
09/09/2018  08:39 AM             1,635 Multiply.java
09/09/2018  08:39 AM             1,427 MultiplyResponse.java
09/09/2018  08:39 AM             2,209 ObjectFactory.java
09/09/2018  08:39 AM               163 package-info.java
09/09/2018  08:39 AM             1,635 Subtract.java
09/09/2018  08:39 AM             1,427 SubtractResponse.java
              12 File(s)         21,329 bytes
               2 Dir(s)  22,013,902,848 bytes free

C:\gitworkspace\jax-ws-client-timeout\src\main\cxf\org\tempuri>

5. Calculator Service Clients

We can set the JAX-WS clients’ read and connection timeout values via the BindingProviderPropertie's two constants: CONNECT_TIMEOUT and REQUEST_TIMEOUT.

5.1 JAX-WS Client

In this step, I will create the JAXWS_CalculatorServiceClient class. It has a constructor which sets the read and connection timeouts.

JAXWS_CalculatorServiceClient.java

package jcg.zheng.jaxws.client.timeoutdemo;

import java.util.Map;

import javax.xml.ws.BindingProvider;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.xml.ws.client.BindingProviderProperties;

import jcg.zheng.demo.jaxws.client.calculator.Calculator;
import jcg.zheng.demo.jaxws.client.calculator.CalculatorSoap;

public class JAXWS_CalculatorServiceClient {
	private final Logger lOG = LoggerFactory.getLogger(this.getClass());

	private CalculatorSoap service;

	public JAXWS_CalculatorServiceClient() {
		super();
		Calculator calculator = new Calculator();
		service = calculator.getCalculatorSoap();
	}

	public JAXWS_CalculatorServiceClient(Integer connectTimeoutInMS, Integer readTimeoutInMS) {
		this();
		if (readTimeoutInMS != null || connectTimeoutInMS != null) {
			Map requestCtx = ((BindingProvider) service).getRequestContext();
			lOG.info("JAX_WS Client Read_Timeout=" + readTimeoutInMS + " Connect_Timeout=" + connectTimeoutInMS);
			requestCtx.put(BindingProviderProperties.REQUEST_TIMEOUT, readTimeoutInMS);
			requestCtx.put(BindingProviderProperties.CONNECT_TIMEOUT, connectTimeoutInMS);
		}
	}

	public int addTwoNumber(int num1, int num2) {
		return service.add(num1, num2);
	}
}

5.2 CXF Client

In this step, I will create the CXF_CalculatorServiceClient class  similar to JAXWS_CalculatorServiceClient but with the stubs generated from the CXF plugin.

CXF_CalculatorServiceClient.java

package jcg.zheng.jaxws.client.timeoutdemo;

import java.util.Map;

import javax.xml.ws.BindingProvider;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tempuri.*;

import com.sun.xml.ws.client.BindingProviderProperties;

public class CXF_CalculatorServiceClient {
	private final Logger lOG = LoggerFactory.getLogger(this.getClass());

	private CalculatorSoap service;

	public CXF_CalculatorServiceClient() {
		super();
		Calculator calculator = new Calculator();
		service = calculator.getCalculatorSoap();
	}

	public CXF_CalculatorServiceClient(Integer connectTimeoutInMS, Integer readTimeoutInMS) {
		this();
		if (readTimeoutInMS != null || connectTimeoutInMS != null) {
			Map requestCtx = ((BindingProvider) service).getRequestContext();
			lOG.info("CXF JAX_WS Client Read_Timeout=" + readTimeoutInMS + " Connect_Timeout=" + connectTimeoutInMS);
			requestCtx.put(BindingProviderProperties.REQUEST_TIMEOUT, readTimeoutInMS);
			requestCtx.put(BindingProviderProperties.CONNECT_TIMEOUT, connectTimeoutInMS);
		}
	}

	public int timesTwoNumber(int num1, int num2) {
		return service.multiply(num1, num2);
	}
}

5.3 Demo Client Timeout with Junit Test

In this step, I will create a ServiceClientTimeoutTestto test the timeout settings.

ServiceClientTimeoutTest.java

package jcg.zheng.jaxws.client.timeoutdemo;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class ServiceClientTimeoutTest {

	private static final int READ_TIMEOUT_OK = 1000;
	private static final int READ_TIMEOUT_EXCEPTION = 10;
	private static final int CONNECT_TIMEOUT_OK = 10;

	private JAXWS_CalculatorServiceClient jaxCalculatorService;
	private CXF_CalculatorServiceClient cxfCalculatorService;

	@Test
	public void jaxwsClient_returns_data_happyPath() {
		jaxCalculatorService = new JAXWS_CalculatorServiceClient(CONNECT_TIMEOUT_OK, READ_TIMEOUT_OK);
		int sum = jaxCalculatorService.addTwoNumber(3, 4);
		assertEquals(7, sum);
	}

	@Test
	public void cxfClient_returns_data_happyPath() {
		cxfCalculatorService = new CXF_CalculatorServiceClient(CONNECT_TIMEOUT_OK, READ_TIMEOUT_OK);
		int product = cxfCalculatorService.timesTwoNumber(3, 4);
		assertEquals(12, product);
	}

	@Test(expected = javax.xml.ws.WebServiceException.class)
	public void jaxwsClient_throw_Exception_when_fails_to_read() {
		jaxCalculatorService = new JAXWS_CalculatorServiceClient(CONNECT_TIMEOUT_OK, READ_TIMEOUT_EXCEPTION);
		jaxCalculatorService.addTwoNumber(3, 4);
	}

	@Test(expected = javax.xml.ws.WebServiceException.class)
	public void cxfClient_throw_Exception_when_fails_to_read() {
		cxfCalculatorService = new CXF_CalculatorServiceClient(CONNECT_TIMEOUT_OK, READ_TIMEOUT_EXCEPTION);
		cxfCalculatorService.timesTwoNumber(3, 4);
	}

}

6. JDK Timeout

JDK provides a list of network properties.  We are interested in the defaultConnectionTimeout and the defaultReadTimeout, which specifies the default connection and read timeout for the protocol handler used by java.net.URLConnection.

  • sun.net.client.defaultConnectTimeout – the timeout in milliseconds to establish the connection to the host.
  • sun.net.client.defaultReadTimeout – the timeout in milliseconds when reading from input stream when a connection is established to a resource.

In this step, I will create a Java application which sets up the JDK network connection timeout properties.

TimeoutDemo .java

package jcg.zheng.jaxws.client.timeoutdemo;

import java.util.Scanner;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TimeoutDemo {
	private static final Logger LOG = LoggerFactory.getLogger(TimeoutDemo.class);

	private static final String JDK_READ_TIMEOUT = "sun.net.client.defaultReadTimeout";
	private static final String JDK_CONNECTION_TIMEOUT = "sun.net.client.defaultConnectTimeout";

	public static void main(String[] args) {
		JAXWS_CalculatorServiceClient calculator = null;
		CXF_CalculatorServiceClient calculator_cxf = null;
		Scanner scanIn = new Scanner(System.in);

		displayJVMTimeout();

		System.out.println("Enter JVM Timeout in Milliseconds: (-1 to ignore) ");
		String jvmTimeoutInput = scanIn.nextLine();
		System.out.println("Enter JAX-WS Client Timeout in Milliseconds: (-1 to ignore) ");
		String clientTimeoutInput = scanIn.nextLine();
		if( jvmTimeoutInput.equalsIgnoreCase("-1")) {
			LOG.info("Ingore JVM Timeout setting.");
		}
		else {
			setTimeOutWithJVMProperties(jvmTimeoutInput);
			displayJVMTimeout();
		}		

		if (clientTimeoutInput.equalsIgnoreCase("-1")) {
			LOG.info("Ingore Client Timeout setting.");
			calculator = new JAXWS_CalculatorServiceClient();
			calculator_cxf = new CXF_CalculatorServiceClient();
		} else {
			Integer timeoutInt = Integer.parseInt(clientTimeoutInput);
			calculator = new JAXWS_CalculatorServiceClient(timeoutInt, timeoutInt);
			calculator_cxf = new CXF_CalculatorServiceClient(timeoutInt, timeoutInt);
		}

		try {
			int sum = calculator.addTwoNumber(3, 4);
			LOG.info("Calculator.add returns: " + sum + " for 3 + 4");
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			int product = calculator_cxf.timesTwoNumber(4, 5);
			LOG.info("Calculator.multiply returns: " + product + " for 4 x 5 ");
		} catch (Exception e) {
			e.printStackTrace();
		}
		scanIn.close();
	}

	private static void setTimeOutWithJVMProperties(String timeoutValue) {
		LOG.info("Update the JVM timeout setting:" + timeoutValue);
		System.setProperty(JDK_CONNECTION_TIMEOUT, timeoutValue);
		System.setProperty(JDK_READ_TIMEOUT, timeoutValue);

	}

	private static void displayJVMTimeout() {
		System.out.println("Current JDK Connection Timeout setting:" + System.getProperty(JDK_CONNECTION_TIMEOUT));
		System.out.println("Current JDK Read Timeout setting:" + System.getProperty(JDK_READ_TIMEOUT));
	}

}

6.1 Demo 1

Execute TimeoutDemo as a Java application. Use the default value by ignoring the timeout setting.

Console Output

Current JDK Connection Timeout setting:null
Current JDK Read Timeout setting:null
Enter JVM Timeout in Milliseconds: (-1 to ignore) 
-1
Enter JAX-WS Client Timeout in Milliseconds: (-1 to ignore) 
-1
11:47:51.422 [main] INFO jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo - Ingore JVM Timeout setting.
11:47:51.433 [main] INFO jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo - Ingore Client Timeout setting.
11:47:52.886 [main] INFO jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo - Calculator.add returns: 7 for 3 + 4
11:47:52.981 [main] INFO jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo - Calculator.multiply returns: 20 for 4 x 5 

6.2 Demo 2

Execute TimeoutDemo as a Java application. Set the JVM timeout to 10 seconds and ignore the client’s timeout setting.

Console Output

Current JDK Connection Timeout setting:null
Current JDK Read Timeout setting:null
Enter JVM Timeout in Milliseconds: (-1 to ignore) 
10000
Enter JAX-WS Client Timeout in Milliseconds: (-1 to ignore) 
-1
11:52:38.623 [main] INFO jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo - Update the JVM timeout setting:10000
Current JDK Connection Timeout setting:10000
Current JDK Read Timeout setting:10000
11:52:38.635 [main] INFO jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo - Ingore Client Timeout setting.
11:52:40.098 [main] INFO jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo - Calculator.add returns: 7 for 3 + 4
11:52:40.239 [main] INFO jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo - Calculator.multiply returns: 20 for 4 x 5 

6.3 Demo 3

Execute TimeoutDemo as a Java application. Set the client’s timeout to 10 seconds and JVM timeout to 1 ms.

Console Output

Current JDK Connection Timeout setting:null
Current JDK Read Timeout setting:null
Enter JVM Timeout in Milliseconds: (-1 to ignore) 
1
Enter JAX-WS Client Timeout in Milliseconds: (-1 to ignore) 
10000
11:53:41.421 [main] INFO jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo - Update the JVM timeout setting:1
Current JDK Connection Timeout setting:1
Current JDK Read Timeout setting:1
Exception in thread "main" javax.xml.ws.WebServiceException: Failed to access the WSDL at: http://www.dneonline.com/calculator.asmx?wsdl. It failed with: 
	connect timed out.
	at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:162)
	at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:144)
	at com.sun.xml.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:263)
	at com.sun.xml.ws.client.WSServiceDelegate.(WSServiceDelegate.java:226)
	at com.sun.xml.ws.client.WSServiceDelegate.(WSServiceDelegate.java:174)
	at com.sun.xml.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:104)
	at javax.xml.ws.Service.(Service.java:77)
	at jcg.zheng.demo.jaxws.client.calculator.Calculator.(Calculator.java:42)
	at jcg.zheng.jaxws.client.timeoutdemo.JAXWS_CalculatorServiceClient.(JAXWS_CalculatorServiceClient.java:22)
	at jcg.zheng.jaxws.client.timeoutdemo.JAXWS_CalculatorServiceClient.(JAXWS_CalculatorServiceClient.java:27)
	at jcg.zheng.jaxws.client.timeoutdemo.TimeoutDemo.main(TimeoutDemo.java:39)
Caused by: java.net.SocketTimeoutException: connect timed out
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at sun.net.NetworkClient.doConnect(NetworkClient.java:178)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)
	at sun.net.www.http.HttpClient.(HttpClient.java:211)
	at sun.net.www.http.HttpClient.New(HttpClient.java:308)
	at sun.net.www.http.HttpClient.New(HttpClient.java:326)
	at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1168)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1104)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:998)
	at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:932)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1512)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
	at java.net.URL.openStream(URL.java:1038)
	at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.createReader(RuntimeWSDLParser.java:805)
	at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.resolveWSDL(RuntimeWSDLParser.java:262)
	at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:129)
	... 9 more

7. JAX-WS Client timeout – Summary

In this article, I demonstrated how to generate JAX-WS clients and set the client read and connection timeout values. There are timeout setting at JVM, OS, and Socket. You should consider these settings when troubleshooting the timeout issues.

8. Download the Source Code

This tutorial consists of a Maven project which demonstrated how to set JAX-WS Client connection and request timeout values.

Download
You can download the full source code of this example here: JAX-WS Client Timeout Example

Mary Zheng

Mary has graduated from Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She works as a senior Software Engineer in the telecommunications sector where she acts as a leader and works with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button