How to Set Timeout for JAX-WS WebService Call - java

I'm working on a WebService Client and I want to set a Timeout for my WebService Call. I have tried different approaches but still I'm not able to achieve this. I'm using JAX-WS for code generation from WSDL. I'm using JBoss-eap-5.1 as App Server and JDK1.6.0_27. I found these diff approaches for setting timeout but none of them is working for me.
URL mbr_service_url = new URL(null,GlobalVars.MemberService_WSDL, new URLStreamHandler() {
#Override
protected URLConnection openConnection(URL url) throws IOException {
URL clone_url = new URL(url.toString());
HttpURLConnection clone_urlconnection = (HttpURLConnection) clone_url.openConnection();
// TimeOut settings
clone_urlconnection.setConnectTimeout(10000);
clone_urlconnection.setReadTimeout(10000);
return (clone_urlconnection);
}
});
MemberService service = new MemberService(mbr_service_url);
MemberPortType soap = service.getMemberPort();
ObjectFactory factory = new ObjectFactory();
MemberEligibilityWithEnrollmentSourceRequest request = factory.createMemberEligibilityWithEnrollmentSourceRequest();
request.setMemberId(GlobalVars.MemberId);
request.setEligibilityDate(value);
((BindingProvider) soap).getRequestContext().put(com.sun.xml.ws.client.BindingProviderProperties.REQUEST_TIMEOUT, 10000);
((BindingProvider) soap).getRequestContext().put(com.sun.xml.ws.client.BindingProviderProperties.CONNECT_TIMEOUT, 10000);
((BindingProvider) soap).getRequestContext().put(com.sun.xml.internal.ws.client.BindingProviderProperties.REQUEST_TIMEOUT, 10000);
((BindingProvider) soap).getRequestContext().put(com.sun.xml.internal.ws.client.BindingProviderProperties.CONNECT_TIMEOUT, 10000);
((BindingProvider) soap).getRequestContext().put(com.sun.xml.ws.developer.JAXWSProperties.REQUEST_TIMEOUT, 10000);
((BindingProvider) soap).getRequestContext().put(com.sun.xml.ws.developer.JAXWSProperties.CONNECT_TIMEOUT, 10000);
((BindingProvider) soap).getRequestContext().put(com.sun.xml.internal.ws.developer.JAXWSProperties.REQUEST_TIMEOUT, 10000);
((BindingProvider) soap).getRequestContext().put(com.sun.xml.internal.ws.developer.JAXWSProperties.CONNECT_TIMEOUT, 10000);
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
MemberEligibilityWithEnrollmentSourceResponse response = soap.getMemberEligibilityWithEnrollmentSource(request);
logger.log("Call to member service finished.");
For now what I have done is, I have called my webservice method from inside an executor. I know its not a good approach, but its working for me. Guys please help me to do it in a proper way.
logger.log("Parameters set for createorUpdateContact call.\nGoing in Executor Service.");
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
#Override
public void run() {
try {
response = soap.getMemberEligibilityWithEnrollmentSource(request);
} catch (MemberServiceException ex) {
logger.log("Exception in call to WebService", ex.fillInStackTrace());
}
}
});
executorService.shutdown();
try {
executorService.awaitTermination(GlobalVars.WSCallTimeOut, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
logger.log("Thread Interrupted!", ex);
executorService.shutdownNow();
}

You could try these settings (they are paired to be used in pairs)
BindingProviderProperties.REQUEST_TIMEOUT
BindingProviderProperties.CONNECT_TIMEOUT
BindingProviderProperties should be from com.sun.xml.internal.WS.client
Or the strings for JBoss:
javax.xml.ws.client.connectionTimeout
javax.xml.ws.client.receiveTimeout
All properties to be put on getRequestContext() in milliseconds.
(BindingProvider)wsPort).getRequestContext().put(BindingProviderProperties.REQUEST_TIMEOUT, yourTimeoutInMillisec);
For JBoss specifically, you might want to use the property StubExt.PROPERTY_CLIENT_TIMEOUT from org.jboss.ws.core.StubExt. See this thread for details.

Like kolossus said you should use:
com.sun.xml.internal.ws.client.BindingProviderProperties
And String values are:
com.sun.xml.internal.ws.connect.timeout
com.sun.xml.internal.ws.request.timeout
Although internal packages shouldn't be used, this is the only way if you work with default JDK6. So, in this case setting receive and connect timeout should be done with:
bindingProvider.getRequestContext().put(BindingProviderProperties.REQUEST_TIMEOUT,requestTimeoutMs);
bindingProvider.getRequestContext().put(BindingProviderProperties.CONNECT_TIMEOUT,connectTimeoutMs);
But beware, constant values are different if you are using other JAXWS reference implementation, i.e. JAXWS-RT 2.1.4 BindingProviderProperties:
com.sun.xml.ws.client.BindingProviderProperties
you will have different String values for REQUEST_TIMEOUT and CONNECT_TIMEOUT:
com.sun.xml.ws.request.timeout
com.sun.xml.ws.connect.timeout

For me setting javax.xml.ws.client.connectionTimeout and javax.xml.ws.client.receiveTimeout solved the problem.
((BindingProvider)port).getRequestContext().put("javax.xml.ws.client.connectionTimeout", timeout);
((BindingProvider)port).getRequestContext().put("javax.xml.ws.client.receiveTimeout", timeout);
refer link

Setting the following options works for me. I am using the Metro JAXWS implementation.
((BindingProvider)portType).getRequestContext().put(JAXWSProperties.CONNECT_TIMEOUT, 10000);
((BindingProvider) portType).getRequestContext().put(JAXWSProperties.REQUEST_TIMEOUT, 50000);
portType is the Web Service endpoint interface.
Values of the above fields from the com.sun.xml.internal.ws.developer.JAXWSProperties
public static final java.lang.String CONNECT_TIMEOUT = "com.sun.xml.internal.ws.connect.timeout";
public static final java.lang.String REQUEST_TIMEOUT = "com.sun.xml.internal.ws.request.timeout";

Upgrade jbossws-native library and use StubExt.PROPERTY_CLIENT_TIMEOUT
For upgrading jbossws-native, follow this link.
*jbossws-native-3.4.0 is the latest supported version for Jboss 5.1.0GA. You can see JBossWS - Supported Target Containers
This worked for me

I have a old installation runtime that have this environment:
Jdk-1.5, Jboss-4.2.3.GA and the WSClient was created by JAX-WS specification 2.0.
to activate Soap Request Timeout I use the follow code
((BindingProvider)port).getRequestContext().put(org.jboss.ws.core.StubExt.PROPERTY_CLIENT_TIMEOUT, String.valueOf(readTimeout));
and the jar jbossws-client.jar copied in jboss-4.2.3.GA\server\default\lib\

Related

How to register a service too ZooKeeper using Curator.x.discovery

I am trying to register a simple REST service on int port,
to ZooKeeper server at localhost:2181.
I checked path ls / using zooClient too.
Any ideas?
private static void registerInZookeeper(int port) throws Exception {
CuratorFramework curatorFramework = CuratorFrameworkFactory
.newClient("localhost:2181", new RetryForever(5));
curatorFramework.start();
ServiceInstance<Object> serviceInstance = ServiceInstance.builder()
.address("localhost")
.port(port)
.name("worker")
.uriSpec(new UriSpec("{scheme}://{address}:{port}"))
.build();
ServiceDiscoveryBuilder.builder(Object.class)
.basePath("myNode")
.client(curatorFramework)
.thisInstance(serviceInstance)
.build()
.start();
Optional.ofNullable(curatorFramework.checkExists().forPath("/zookeeper")).ifPresent(System.out::println);
Optional.ofNullable(curatorFramework.checkExists().forPath("/myNode")).ifPresent(System.out::println);
}
I kept receiving Received packet at server of unknown type 15 from Zoo Server, because of compatibility issues
the registration code here looks correct. In order to print registered instances the following code can be executed:
Optional.ofNullable(curatorFramework.getChildren().forPath("/myNode/worker"))
.orElse(Collections.emptyList())
.forEach(childNode -> {
try {
System.out.println(childNode);
System.out.println(new String(curatorFramework.getData().forPath("/myNode/worker/" + childNode)));
} catch (Exception e) {
e.printStackTrace();
}
});
The result will be like
07:23:12.353 INFO [main-EventThread] ConnectionStateManager:228 - State change: CONNECTED
48202336-e89b-4724-912b-89620f7c9954
{"name":"worker","id":"48202336-e89b-4724-912b-89620f7c9954","address":"localhost","port":1000,"sslPort":null,"payload":null,"registrationTimeUTC":1515561792319,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}
Creating your curator framework with zk34 (the version used by kafka) compatibility should fix your problem
private CuratorFramework buildFramework(String ip) {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
return CuratorFrameworkFactory.builder().zk34CompatibilityMode(true).connectString(ip + ":2181")
.retryPolicy(retryPolicy).build();
}
Please note that curator will just try its best and some new methods (eg. creatingParentsIfNeeded (ok) vs creatingParentContainersIfNeeded (ko)) will fail.

MockRestServiceServer simulate backend timeout in integration test

I am writing some kind of integration test on my REST controller using MockRestServiceServer to mock backend behaviour.
What I am trying to achieve now is to simulate very slow response from backend which would finally lead to timeout in my application. It seems that it can be implemented with WireMock but at the moment I would like to stick to MockRestServiceServer.
I am creating server like this:
myMock = MockRestServiceServer.createServer(asyncRestTemplate);
And then I'm mocking my backend behaviour like:
myMock.expect(requestTo("http://myfakeurl.blabla"))
.andExpect(method(HttpMethod.GET))
.andRespond(withSuccess(myJsonResponse, MediaType.APPLICATION_JSON));
Is it possible to add some kind of a delay or timeout or other kind of latency to the response (or maybe whole mocked server or even my asyncRestTemplate)? Or should I just switch to WireMock or maybe Restito?
You can implement this test functionality this way (Java 8):
myMock
.expect(requestTo("http://myfakeurl.blabla"))
.andExpect(method(HttpMethod.GET))
.andRespond(request -> {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
} catch (InterruptedException ignored) {}
return new MockClientHttpResponse(myJsonResponse, HttpStatus.OK);
});
But, I should warn you, that since MockRestServiceServer simply replaces RestTemplate requestFactory any requestFactory settings you'd make will be lost in test environment.
If you control timeout in your http client and use for example 1 seconds you can use mock server delay
new MockServerClient("localhost", 1080)
.when(
request()
.withPath("/some/path")
)
.respond(
response()
.withBody("some_response_body")
.withDelay(TimeUnit.SECONDS, 10)
);
If you want to drop connection in Mock Server use mock server error action
new MockServerClient("localhost", 1080)
.when(
request()
.withPath("/some/path")
)
.error(
error()
.withDropConnection(true)
);
Approach that you can go for:
Specifying the responsebody either with Class Path resource or normal string content. More detailed version of what Skeeve suggested above
.andRespond(request -> {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(5)); // Delay
} catch (InterruptedException ignored) {}
return withStatus(OK).body(responseBody).contentType(MediaType.APPLICATION_JSON).createResponse(request);
});
In Restito, there is a buil-in function to simulate timeout:
import static com.xebialabs.restito.semantics.Action.delay
whenHttp(server).
match(get("/something")).
then(delay(201), stringContent("{}"))
In general, you can define your custom request handler, and do a nasty Thread.sleep() there.
This would be possible in Restito with something like this.
Action waitSomeTime = Action.custom(input -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return input;
});
whenHttp(server).match(get("/asd"))
.then(waitSomeTime, ok(), stringContent("Hello World"))
Not sure about Spring, however. You can easily try. Check DefaultResponseCreator for inspiration.

Timer in Java/ATG - Web Services call

I have generated a request for web services. I need to do do a check on my call. If the response is not returned within 5 seconds, another request will be shooted.
Pseudo Code :
webServiceClass response = xyz.getData();
If the response is not obtained in 5 seconds - send another request CheckData() to web services.This should be done for a maximum of 5 times.
I need to do this without using threads.
Try something like this (not tested but should give you the idea):
final MultiThreadedHttpConnectionManager httpConnections = new MultiThreadedHttpConnectionManager();
final HttpConnectionManagerParams connParams = manager.getParams();
final HttpClient httpClient = new HttpClient(manager);
final int connectionTimeout = 5000;
connParams.setConnectionTimeout(connectionTimeout);
try
{
// your web service call goes here
}
catch(ConnectTimeoutException cte)
{
if (isLoggingError())
{
logError(cte.getMessage());
}
}
catch(IOException ioe)
{
if (isLoggingError())
{
logError(ioe.getMessage());
}
}
finally
{
// make sure we always release the connection
method.releaseConnection();
}

Apache Mina + SSL + Android not working

I'm developing an Android app using Apache Mina for network IO. Non-SSL connections (reading, writing) work fine, but as soon as I add an SSL filter things stop working.
I also tried pure SSL sockets and they work fine.
This is my Mina connection code (in a separate networking thread):
IoConnector connector = new NioSocketConnector();
connector.getSessionConfig().setReadBufferSize(2048);
SocketSessionConfig cfg = (SocketSessionConfig)connector.getSessionConfig();
cfg.setTcpNoDelay(true);
SslContextFactory f = new SslContextFactory();
f.setTrustManagerFactory(new BogusTrustManagerFactory());
f.setProtocol("SSL");
try {
filter = new SslFilter(f.newInstance(), true);
} catch (Exception e) {
Log.d(TAG, "Exception: ", e);
return;
}
filter.setUseClientMode(true);
connector.getFilterChain().addLast("sslFilter", filter);
connector.getFilterChain().addLast("logger", new LoggingFilter());
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("ASCII"))));
connector.setHandler(new MinaClientHandler());
ConnectFuture future = connector.connect(new InetSocketAddress("10.0.1.9", 7072));
future.awaitUninterruptibly();
if (!future.isConnected())
{
Log.d(TAG, "not connected, return");
return;
}
IoSession session = future.getSession();
session.getConfig().setUseReadOperation(true);
session.getCloseFuture().awaitUninterruptibly();
//System.out.println(session.read().getMessage());
Log.d(TAG, "after writting");
connector.dispose();
In my IoHandlerAdapter I have the following override:
#Override
public void sessionOpened(IoSession session)
{
session.write(IoBuffer.wrap(data)); // byte array
}
Not my actual code, but it reproduces the problem.
On the server side I see that the connection is accepted an the handshake succeeds. But on the client side nothing is sent over the socket. I have tried the same code in a desktop Java application and it also works.
Also if I move the write call just after IoSession session = future.getSession(); the same thing happens.
Has anyone had similar issues? Are there known issues with Mina on Android? Am I missing some session config options?
Since normal SSL sockets work, that is a workaround, but I would rather not rewrite all my networking code.

Why does the ProxySelector is null in HttpUrlConnection.plainConnect()?

I have to call a WS that requires custom client authentication. This authentication is done by a program running on the client and listening on http://127.0.0.1:80.
So I add a ProxySelector when starting up like this :
final ProxySelector ps = new ProxySelector() {
#Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
ioe.printStackTrace();
}
#Override
public List<Proxy> select(URI uri) {
final List<Proxy> proxy = new ArrayList<Proxy>();
final SocketAddress adr = new InetSocketAddress("127.0.0.1", 80);
final Proxy p = new Proxy(Proxy.Type.HTTP, adr);
proxy.add(p);
return proxy;
};
ProxySelector.setDefault(ps);
This use to work fine, but after some refactoring (not related to WS calls), instead of having http://my.server.com as URI input, I have socket://my.server.com and it fails with a "Unknown proxy type : HTTP", what seems quite normal with SOCKET scheme...
The difference between my old application and the new one is the behavior during HttpUrlConnection.plainConnect() was not the same. Indeed, the working version calls my ProxySelector with the right URI (line 922 of http://www.docjar.com/html/api/sun/net/www/protocol/http/HttpURLConnection.java.html),
whereas the new version jump to line 959 and start creating a new underlying connection, which ends up with a socket:// scheme.
So the difference lies in following lines :
ProxySelector sel =
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<ProxySelector>() {
public ProxySelector run() {
return ProxySelector.getDefault();
}
});
This used to return my ProxySelector as "sel" but now returns null.
Can someone explain me what exactly means these lines, and why the result is not the same than in my old app ?
Eventually, I figured this out !
The jaxws-maven-plugin used to generate WS client was in version 1.10 in the working application, and changed to 1.12 in the new one, what introduced the changes in HttpUrlConnection as explained above.
Still don't know what happened, and which dependent library has changed between 1.10 and 1.12 but there is a quite BIG difference in the way of creating HttpConnections :)
Thanks anyway for those who read my weird question... ^^

Categories