Showing posts with label Timeout. Show all posts
Showing posts with label Timeout. Show all posts

Sunday, May 21, 2017

Springframework Async annotation and ThreadExcutor's AbortPolicy

The Springframework has @Async annotation.

it simplifies the asynchronous method execution and hides the implementation details. In order to have a dependable asynchronous execution mechanism, few more factors need our attention.

First, the sample of the usage of the Async annotation:

@Async
void doSomething() {
    // activities will be executed asynchronously
}

@Async("anExecutor")
Future<String> doThenReturnSomething(String id) {
    // will be executed asynchronously
}

Other possible return types:

JDK 8’s java.util.concurrent.CompletableFuture

boolean cancel(boolean mayInterruptIfRunning)
boolean complete(T value)

Spring’s org.springframework.util.concurrent.ListenableFuture 

void      addCallback(ListenableFutureCallback<? super T> callback)
void      addCallback(SuccessCallback<? super T> successCallback, FailureCallback failureCallback)

JBoss’s org.jboss.threads.AsyncFuture

Void asyncCancel(boolean interruptionDesired)
AsyncFuture.Status getStatus()

ThreadPoolTaskExecutor This implementation is the most commonly used one.

<task:executor
        id="executorWithCallerRunsPolicy"
        pool-size="5-25"
        queue-capacity="100"
        keep-alive="120"
        rejection-policy="CALLER_RUNS"/>
From Springframework document:
By default, the queue is unbounded, but this is rarely the desired configuration, because it can lead to OutOfMemoryErrors if enough tasks are added to that queue while all pool threads are busy.

TaskRejectedExceptionAbortPolicyDiscardPolicy or DiscardOldestPolicyCallerRunsPolicy

First, let’s consider the case, as mentioned above, when a task is rejected. By default, when a task is rejected, a thread pool executor will throw a TaskRejectedException. However, the rejection policy is actually configurable. The exception is thrown when using the default rejection policy which is the AbortPolicy implementation. For applications where some tasks can be skipped under heavy load, either the DiscardPolicy or DiscardOldestPolicy may be configured instead. Another option that works well for applications that need to throttle the submitted tasks under heavy load is the CallerRunsPolicy. Instead of throwing an exception or discarding tasks, that policy will simply force the thread that is calling the submit method to run the task itself. The idea is that such a caller will be busy while running that task and not able to submit other tasks immediately. Therefore it provides a simple way to throttle the incoming load while maintaining the limits of the thread pool and queue. Typically this allows the executor to "catch up" on the tasks it is handling and thereby frees up some capacity on the queue, in the pool, or both. Any of these options can be chosen from an enumeration of values available for the 'rejection-policy' attribute on the 'executor' element.
The keep-alive setting determines the time limit (in seconds) for which threads may remain idle before being terminated. If there are more than the core number of threads currently in the pool, after waiting this amount of time without processing a task, excess threads will get terminated.
Finally,
When actions are enclosed in tasks (such as FutureTask) either explicitly or via methods such as submit, these task objects catch and maintain computational exceptions, and so they do not cause abrupt termination, and the internal exceptions are not passed to this method. Please make sure that the calling method handles the exception properly.
Inside the asynchronous task, most likely, a remote service call or database access will be invoked. Please configure proper timeout so that thread will not be blocked or thread will not hang.

Saturday, May 20, 2017

RestClient 2.x Customization of Proxy and Connection Timeout

If there is a need to configure proxy setting, or connection timeout setting for RestEasy client, here is the code sample.


public class RestClientUtil {
private static final Logger logger = LoggerFactory.getLogger(RestClientUtil.class);

public static String buildQueryPath(@NotNull final URI uri, final String id) {
logger.debug("uri: " + uri + ", id:" + id);
final StringBuilder finalUri = new StringBuilder(uri.toString());
if (id != null && !id.isEmpty()) {
finalUri.append("/").append(id).toString();
}

logger.debug("finalUri: " + finalUri.toString());
return finalUri.toString();
}

public static ClientRequest createClientRequest(@NotNull final String finalUri, final String proxyHost, final int proxyPort,
final boolean trustAllCerts) {
final ClientRequest request;

if (proxyHost != null) {
final DefaultHttpClient httpClient;
if (trustAllCerts == true) {
try {
httpClient = createAllTrustingClient();
} catch (GeneralSecurityException e) {
throw new IllegalStateException("failed in createAllTrustingClient", e);
}
} else {
httpClient = new DefaultHttpClient();
}

HttpParams params = setConnectionParams(httpClient);

final HttpHost proxy = new HttpHost(proxyHost, proxyPort);
params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
final ApacheHttpClient4Executor executor = new ApacheHttpClient4Executor(httpClient);
request = new ClientRequest(finalUri, executor);
} else {
final DefaultHttpClient httpClient;
if (trustAllCerts == true) {
try {
httpClient = createAllTrustingClient();
} catch (GeneralSecurityException e) {
throw new IllegalStateException("failed in createAllTrustingClient", e);
}
final ApacheHttpClient4Executor executor = new ApacheHttpClient4Executor(httpClient);
request = new ClientRequest(finalUri, executor);
} else {
request = new ClientRequest(finalUri);
}
}
return request;
}

protected static HttpParams setConnectionParams(final DefaultHttpClient httpClient) {
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);
return params;
}

public static DefaultHttpClient createAllTrustingClient() throws GeneralSecurityException {
final SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));

final TrustStrategy trustStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
};

final SSLSocketFactory factory = new SSLSocketFactory(trustStrategy, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
registry.register(new Scheme("https", 443, factory));

final ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(registry);
mgr.setMaxTotal(1000);
mgr.setDefaultMaxPerRoute(1000);

final DefaultHttpClient client = new DefaultHttpClient(mgr, new DefaultHttpClient().getParams());
return client;
}
}