Java CompletableFuture - main class not terminated - java-8

I am trying to implment CompletableFuture which invokes a dummy callback method when completed.
However, after adding CompletableFuture.get() method my main class doesn't terminate.
I tried replacing CompletableFuture.get() with Thread.sleep(5000) but it doesn't seem to be right approach.
Please suggest what is causing CompletableFuture.get() to keep blocking even if the thread is complete.
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.IntStream;
public class CallableAsyncWithCallBack {
public static void main(String[] args) throws InterruptedException {
CompletableFuture<String> compFuture=new CompletableFuture<String>();
compFuture.supplyAsync(()->{
//Compute total
long count=IntStream.range(Integer.MIN_VALUE, Integer.MAX_VALUE).count();
return ""+count;
}).thenApply(retVal->{
try {
return new CallBackAsynchClass(retVal).toString();
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
);
System.out.println("Main Thread 1");
try {
compFuture.get();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("Lock cleared");
}
}
class CallBackAsynchClass
{
String returnVal="";
public CallBackAsynchClass(String ret) throws InterruptedException, ExecutionException {
System.out.println("Callback invoked:"+ret);
returnVal=ret;
}
#Override
public String toString() {
return "CallBackAsynchClass [returnVal=" + returnVal + "]";
}
}
I am expecting "Lock cleared" to be outputted but .get() seems to be holding up the lock.

.thenApply function returns a new instance of CompletableFuture, and it's this instance that you need to use, try using this way instead :
public class CallableAsyncWithCallBack {
public static void main(String[] args) throws InterruptedException {
CompletableFuture<String> compFuture = CompletableFuture.supplyAsync(() -> {
//Compute total
long count = IntStream.range(Integer.MIN_VALUE, Integer.MAX_VALUE).count();
return "" + count;
});
CompletableFuture<String> future = compFuture.thenApply(retVal -> {
try {
return new CallBackAsynchClass(retVal).toString();
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ""; });
System.out.println("Main Thread 1");
try {
future.get();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("Lock cleared");
}
}
Hope this helps

Related

Disable redis when many timeouts using spring boot

I have an application deployed in AWS EC2, some time (rare), I can't connect and execute any command in redis, I am investigating the root cause of this problem.
I am using Spring boot + Redis (Elasticcache).
I am using a wrapper to catch any exception to continue the request process.
My wrapper:
class RedisCacheWrapper implements Cache {
private final Cache delegate;
public RedisCacheWrapper(Cache redisCache) {
Assert.notNull(redisCache, "delegate cache must not be null");
this.delegate = redisCache;
}
#Override
public String getName() {
try {
return delegate.getName();
} catch (Exception e) {
return handleException(e);
}
}
#Override
public Object getNativeCache() {
try {
return delegate.getNativeCache();
} catch (Exception e) {
return handleException(e);
}
}
#Override
public ValueWrapper get(Object key) {
try {
return delegate.get(key);
} catch (Exception e) {
return handleException(e);
}
}
#Override
public <T> T get(Object o, Class<T> type) {
try {
return delegate.get(o, type);
} catch (Exception e) {
return handleException(e);
}
}
#Override
public <T> T get(Object o, Callable<T> callable) {
try {
return delegate.get(o, callable);
} catch (Exception e) {
return handleException(e);
}
}
#Override
public void put(Object key, Object value) {
try {
delegate.put(key, value);
} catch (Exception e) {
handleException(e);
}
}
#Override
public ValueWrapper putIfAbsent(Object o, Object o1) {
try {
return delegate.putIfAbsent(o, o1);
} catch (Exception e) {
return handleException(e);
}
}
#Override
public void evict(Object o) {
try {
delegate.evict(o);
} catch (Exception e) {
handleException(e);
}
}
#Override
public void clear() {
try {
delegate.clear();
} catch (Exception e) {
handleException(e);
}
}
private <T> T handleException(Exception e) {
log.error("handleException", e);
return null;
}}
In my redis configuration I set the timeout to 1s. So, when connect/command is not perform after 1s, the redis throws an Exception like this:
Caused by: io.lettuce.core.RedisCommandTimeoutException: Command timed out
My doubt:
There is a good way to disable cache temporary (without any deploy), while redis is not good? For example: Using a circuit break?
I am think do it:
#Cacheable()
myMethodCached(){
myRealMethod();
}
myRealMethod(){}
Put "myMethodCached" in HystrixCommand, if timeout is throwed, then fallback method is performed without using redis.
The problem with this approach is that I need to create a "fallback" for all methods that use cache, I would like to "disable" globally (all cache will be skipped).
Is there a good solution to "disable" redis for a period?
If you are using Spring Data Redis, you can leverage Spring's support for handling these temporary outages and exceptions via a custom exception handler.
Code:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Recommend to set the timeout lower than the default (60000):
spring.cache.type=redis
spring.redis.timeout=100
Then create a custom error handler in the Spring context:
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.context.annotation.Configuration;
#Slf4j
#EnableCaching
#Configuration
public class CacheConfiguration extends CachingConfigurerSupport {
#Override
public CacheErrorHandler errorHandler() {
return new CacheErrorHandler() {
#Override
public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
log.info("Failure getting from cache: " + cache.getName() + ", exception: " + exception.toString());
}
#Override
public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
log.info("Failure putting into cache: " + cache.getName() + ", exception: " + exception.toString());
}
#Override
public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
log.info("Failure evicting from cache: " + cache.getName() + ", exception: " + exception.toString());
}
#Override
public void handleCacheClearError(RuntimeException exception, Cache cache) {
log.info("Failure clearing cache: " + cache.getName() + ", exception: " + exception.toString());
}
};
}
}
Spring should detect the failure after 100 milliseconds and fallback to retrieve the data retrieved via #Cacheable annotated methods normally as if there were a cache-miss. And whenever cache is restored Spring will start pulling from cache again.

#Retryable is not working when calling from a method

Below is my application class. The flow is like the DEToken class from here and from DEToken I call RestConnection where I have the #retryable method.
#SpringBootApplication
#EnableRetry
public class SpringBootTrfficApplication implements CommandLineRunner {
Enter code here
#Autowired
DEToken deToken;
#Autowired
SyncService syncService;
public static void main(String[] args) {
SpringApplication.run(SpringBootTrfficApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
deToken.getToken();
}
}
DEToken class: from getToken I am calling RestConnect where I have the #Retrable method:
#Service
public class DEToken {
private Logger logger = LogManager.getLogger(getClass());
#Autowired
RestConnection restConnection;
#Autowired
private Environment env;
public String accessToken;
public void getToken() {
System.out.println("hello from get token");
//String getJsonPayload = "{\"Query\":{\"RegisterExtensionWithDE\":{\"pid\": \"\",\"providerInsName\":" +
//env.getProperty("provider.ins") + "}}}";
//String str = restConnection.restPost(
// env.getProperty("rest.de.url"), getJsonPayload);
try {
String getJsonPayload =
"{\"Query\":{\"RegisterExtensionWithDE\":{\"pid\": \"\",\"providerInsName\":" +
env.getProperty("provider.ins") + "}}}";
StringBuffer tokenResult =
restConnection.restPost(env.getProperty("rest.de.url"),
getJsonPayload);
System.out.println(tokenResult);
JSONObject xmlJSONObj = XML.toJSONObject(tokenResult.toString());
JSONObject registration = new JSONObject();
if (xmlJSONObj.has("Registration")) {
registration = xmlJSONObj.getJSONObject("Registration");
if (registration.has("accessToken")) {
accessToken = registration.get("accessToken").toString();
}
else
logger.info("no accessToken from DE");
}
else
logger.info("no Registration object from DE");
}
catch (Exception e) {
logger.error("Exception while fetching accesstoken from DE ");
logger.error(e.getMessage());
}
}
}
My REST connection class where I have retryable method:
#Service
public class RestConnection {
private Logger logger = LogManager.getLogger(getClass());
#Autowired
private Environment env;
public void setBaseUrl(String value, String ip) {
//baseUrl = value;
HttpsURLConnection.setDefaultHostnameVerifier(
(hostname, session) -> hostname.equals(ip));
}
/*
* REST post call
*/
#Retryable(value = {IOException.class, ConnectException.class},
maxAttempts = 4,
backoff = #Backoff(5000))
public StringBuffer restPost(String restUrl, String payload) {
StringBuffer sb = new StringBuffer();
HttpURLConnection conn = null;
try {
URL url = new URL(restUrl);
String protocol = url.getProtocol();
if (protocol.toLowerCase().equals("http")) {
conn = (HttpURLConnection)url.openConnection();
}
else if (protocol.toLowerCase().equals("https")) {
//setTrustedCert();
conn = (HttpsURLConnection)url.openConnection();
}
else {
logger.info("Protocol is neither HTTP nor HTTPS");
}
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("version", env.getProperty("de.version"));
conn.setRequestProperty("accessToken", env.getProperty("access.token"));
conn.setRequestProperty("requestHost", env.getProperty("server.de.host"));
conn.setRequestProperty("requestPort", env.getProperty("server.port"));
conn.setRequestProperty("requestProtocol",
env.getProperty("server.de.protocol"));
PrintWriter pout =
new PrintWriter(
new OutputStreamWriter(
conn.getOutputStream(), "UTF-8"),
true);
pout.print(payload);
pout.flush();
pout.close();
InputStream isi = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(isi);
int numCharsRead1;
char[] charArray1 = new char[1024];
while ((numCharsRead1 = isr.read(charArray1)) > 0) {
sb.append(charArray1, 0, numCharsRead1);
}
isr.close();
isi.close();
}
catch (MalformedURLException e) {
logger.error("MalformedURLException in restAccessTokenPOST..." +
e.getMessage());
//e.printStackTrace();
}
catch (IOException e) {
logger.error("IOException in restAccessTokenPOST..." +
e.getMessage());
e.printStackTrace();
}
catch (Exception e) {
logger.error("Exception in restAccessTokenPOST..." +
e.getMessage());
e.printStackTrace();
}
finally {
if (null != conn)
conn.disconnect();
}
return sb;
}
#Recover
public String helpHere(ConnectException cause) {
System.out.println("Recovery place! ConnectException");
return "Hello";
}
#Recover
public String helpHere(IOException cause) {
System.out.println("Recovery place! ArithmeticException");
return "Hello";
}
#Recover
public String helpHere(Exception cause) {
System.out.println("Recovery place! Exception");
return "Hello";
}
#Recover
public String helpHere() {
System.out.println("Recovery place! Exception");
return "Hello";
}
#Recover
public String helpHere(Throwable cause) {
System.out.println("Recovery place! Throwable");
return "Hello";
}
}
Considering you see your function restPost() implementation,
#Retryable(value = {IOException.class, ConnectException.class},
maxAttempts = 4,
backoff = #Backoff(5000))
public StringBuffer restPost(String restUrl, String payload) {
try {
// Your code
}
catch(IOException ex){ // These catch block handles the exception
// and nothing to throw to retryable.
}
catch(MalformedURLException ex){ // More catch blocks that you
// define to handle exception.
}
}
Here you handle all of the exceptions that can be a cause to revoke the retry and recover methods.
Note: Recoverable methods only execute when a exception is thrown, not handled by any try-catch block.
Whatever exception is raised by method restPost() is handled by the method try-catch block itself and there are no exceptions that had been rethrow by a catch block.
Now, Spring-Retry is unable to get any exception (because it is handled by the method try-catch block). So, no recovery method will be executed.
Solution: you should remove those catch blocks from the method definition on which you want to perform retry or recover.
Please do the needful and it will work like a charm... :)

Using Java Stream API in already multi-threaded environment

My application has its own thread pool(myThreadPool) and I am assigning one of its threads(Producer) to read a file via java stream API. But in runtime stream is lost somewhere and never reaches the print method. But when I run the stream in single threaded environment it works. Does it happen because java stream Api uses its own thread pool underneath or is this conceptually wrong?
public class Processor {
public void process() {
ExecutorService myThreadPool = Executors.newFixedThreadPool(3);
myThreadPool.execute(new Producer());
}
private class Producer implements Runnable{
#Override
public void run() {
try (Stream<String> lines = Files.lines(Paths.get("Path"))) {
System.out.println(lines.count());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I don't know what you have happen. but I can give you an advice (maybe your program exited and Producer is not terminated). copy this code and see what wrong of your code.
public class Processor {
public void process() {
ExecutorService myThreadPool = Executors.newFixedThreadPool(3);
try {
myThreadPool.execute(new Producer());
Thread.currentThread().join();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private class Producer implements Runnable {
#Override
public void run() {
try (Stream<String> lines = Files.lines(Paths.get("Path"))) {
System.out.println(lines.count());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
OR
public class Processor {
public void process() {
ExecutorService myThreadPool = Executors.newFixedThreadPool(3);
try {
myThreadPool.submit(() -> {
new Producer().run();
return null;
}).get();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private class Producer implements Runnable {
#Override
public void run() {
try (Stream<String> lines = Files.lines(Paths.get("Path"))) {
System.out.println(lines.count());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

What is the impact of using #non thread-safe class?

I have written the following code, as I was trying to understand the situation where I would use ThreadLocals:-
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDF {
private DateFormat df = new SimpleDateFormat("MM/dd/yy");
public String formatCurrentDate() {
System.out.println(">>>>>>>"+Thread.currentThread().getName());
Date d = new Date();
return df.format(d);
}
public String formatFirstOfJanyary1970() {
System.out.println(">>>>>>>" + Thread.currentThread().getName());
Date d = new Date(0);
return df.format(d);
}
public static void main(String[] args) {
TestDF df = new TestDF();
Thread t1 = new Thread(new WorkerThread(df));
Thread t2 = new Thread(new WorkerThread1(df));
t1.start();
t2.start();
}
public static class WorkerThread implements Runnable {
TestDF df;
public WorkerThread(TestDF df) {
this.df = df;
}
#Override
public void run() {
Thread.currentThread().setName("Worker-Thread 1");
System.out.println("Inside Thread1*");
System.out.println("Thread 1 "+df.formatCurrentDate());
System.out.println("Inside Thread1**");
try {
Thread.sleep(5000l);
System.out.println("Inside Thread1***");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static class WorkerThread1 implements Runnable {
TestDF df;
public WorkerThread1(TestDF df) {
this.df = df;
}
#Override
public void run() {
Thread.currentThread().setName("Worker-Thread 2");
System.out.println("Inside Thread2*");
System.out.println("Thread 2 "+df.formatFirstOfJanyary1970());
System.out.println("Inside Thread2**");
try {
Thread.sleep(5000l);
System.out.println("Inside Thread2***");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
The out which I am receiving is as follows:-
Inside Thread1*
Inside Thread2*
>>>>>>>Worker-Thread 2
>>>>>>>Worker-Thread 1
Thread 1 06/09/15 <--
Thread 2 06/09/15 <--
Inside Thread1**
Inside Thread2**
Inside Thread1***
Inside Thread2***
I am aware that SimpleDateFormat is not thread-safe; but still couldn't make out how is happening.

Websocket : Is it possible to know from the program what is the reason for onClose being called

I have a Sample WebSocket Program whown below which works fine
When ever the user closes the browser or if there is any excetion Or any disconnect , the onClose Method is
being called
My question is that , Is it possible to know from the program what is the reason for onClose being called ??
Please share your views , Thanks for reading .
public class Html5Servlet extends WebSocketServlet {
private AtomicInteger index = new AtomicInteger();
private static final List<String> tickers = new ArrayList<String>();
static{
tickers.add("ajeesh");
tickers.add("peeyu");
tickers.add("kidillan");
tickers.add("entammo");
}
/**
*
*/
private static final long serialVersionUID = 1L;
public WebSocket doWebSocketConnect(HttpServletRequest req, String resp) {
//System.out.println("doWebSocketConnect");
return new StockTickerSocket();
}
protected String getMyJsonTicker() throws Exception{
return "";
}
public class StockTickerSocket implements WebSocket.OnTextMessage{
private Connection connection;
private Timer timer;
#Override
public void onClose(int arg0, String arg1) {
System.out.println("onClose called!"+arg0);
}
#Override
public void onOpen(Connection connection) {
//System.out.println("onOpen");
this.connection=connection;
this.timer=new Timer();
}
#Override
public void onMessage(String data) {
//System.out.println("onMessage");
if(data.indexOf("disconnect")>=0){
connection.close();
timer.cancel();
}else{
sendMessage();
}
}
public void disconnect() {
System.out.println("disconnect called");
}
public void onDisconnect()
{
System.out.println("onDisconnect called");
}
private void sendMessage() {
if(connection==null||!connection.isOpen()){
//System.out.println("Connection is closed!!");
return;
}
timer.schedule(new TimerTask() {
#Override
public void run() {
try{
//System.out.println("Running task");
connection.sendMessage(getMyJsonTicker());
}
catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, new Date(),5000);
}
}
}
The signature for onClose is the following ...
#Override
public void onClose(int closeCode, String closeReason) {
System.out.println("onClose called - statusCode = " + closeCode);
System.out.println(" reason = " + closeReason);
}
Where int closeCode is any of the registered Close Status Codes.
And String closeReason is an optional (per protocol spec) close reason message.

Resources