Loop On Exception - java

I have a custom built API for interacting with their messaging system. But this API doesn't give me any way to confirm that I have established a connection aside from when it is unable to connect an exception will be thrown.
When I receive a exception while connected, I have an exception listener that attempts to reconnect to the server. I'd like this to loop on exception to retry the connection. Doing an infinite loop until I am able to connect, or until the program is closed. I attempted to do this with break labels like so:
reconnect: try{
attemptReconnection();
}catch(Exception e){
log.error(e);
break reconnect;
}
but that was unable to find the reconnect label for me, and is a bit to close to using a GOTO statement than I would be comfortable putting into production.

Proceed this way:
do { // optional loop choice
try{
attemptReconnection();
break; // Connection was successful, break out of the loop
} catch(Exception e){
// Exception thrown, do nothing and move on to the next connection attempt (iteration)
log.error(e);
}
}while(true);
If the execution flow reaches the break; instruction then that means that you successfully connected. Otherwise, it will keep moving on to the next iteration. (Note that the loop choice is optional, you can use pretty much any loop you want)

Can't say I have experience with APIs, but I would think something like this would achieve the result you're after.
boolean success = false;
while (!success){
try{
attemptReconnection();
success = true;
}
catch(Exception e){
log.error(e);
}
}
Once attemptReconnection() executes without errors, success would be set to true and terminate the loop.

Have attemptReconnection return true when connection succeds, false otherwise.
The method attemptReconnection should also catch and log the Exception.
Then :
while(!attemptReconnection()){
log.error("Connection failure");
}

I would suggest controlling the reconnection attempts not with a while loop but with a scheduled event. This you can easily initiate multiple connections and implement a back off mechanism not to over-consume resources while trying to reconnect
private ScheduledExecutorService scheduler;
...
public void connect() {
for (int i = 0; i < numberOfConnections; i++) {
final Runnable r = new Runnable() {
int j = 1;
public void run() {
try {
final Connection connection = createNewConnection();
} catch (IOException e) {
//here we do a back off mechanism every 1,2,4,8,16... 512 seconds
final long sleep = j * 1000L;
if (j < 512) {
j *= 2;
} else {
j = 1;
}
LOGGER.error("Failed connect to host:port: {}:{}. Retrying... in {} millis",
host, port, sleep);
LOGGER.debug("{}", e);
scheduler.schedule(this, sleep, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
}
}
};
scheduler.schedule(r, 1, TimeUnit.SECONDS);
}
}
Do not forget to do a scheduler.shutdownNow() if you want to close the application so as to avoid the treadpool being leaking.
You can even implement a reconnect mechanism once you have been connected and you are disconnected by having the listener execute the connect method in case of a status change on the connection.

Related

How to check when polling stopped

I have a message stream, where messages comes which I need to process and then store them in database. In Java, I've written polling code which polls stream and consumes messages every 20 seconds.
This is done inside an infinite for-loop, like below:
for (;;) {
try{
//1. Logic for polling.
//2. Logic for processing the message.
//3. Logic for storing the message in database.
Thread.sleep(20000 - <time taken for above 3 steps >);
} catch(Exception E){
//4. Exception handling.
}
}
This logic runs as expected and the stream is polled, but once in a while it hits an exception or something goes wrong and polling stops.
I want to have a mechanism, that as soon as polling stopped, let's say this for loop is not running for 60 seconds, I should receive a mail or ping.
What is the best way to invoke a method if this for loop is not running for 60 seconds?
I am thinking like, each for-loop execution will ping a heartbeat, and when that heartbeat pinging not received from for-loop then a mail sending is invoked.
There are two different reasons why polling stops making progress, and each needs a different approach:
If the logic throws a Throwable other than an Exception, for instance an Error, the catch does not match, and execution will leave the for-loop, and likely reach the thread's UncaughtExceptionHandler, the default implementation of which logs the exception to System.err and terminates the thread. To prevent this, you should catch Throwable rather than Exception.
The second possibility is that some step in your logic doesn't terminate, for instance due to an infinite loop, a deadlock, waiting for I/O operations, or whatever. In this case, you'll want to take a thread dump to see where the thread is stuck. You can automate this as follows:
class Watchdog {
final Duration gracePeriod;
final Thread watchedThread;
volatile Instant lastProgress;
public Watchdog(Duration gracePeriod) {
this.gracePeriod = gracePeriod;
watchedThread = Thread.currentThread();
everythingIsFine();
var t = new Thread(this::keepWatch);
t.setDaemon(true);
t.start();
}
public void everythingIsFine() {
lastProgress = Instant.now();
}
void keepWatch() {
while (true) {
var silence = Duration.between(lastProgress, Instant.now());
if (silence.compareTo(gracePeriod) > 0) {
System.err.println("Watchdog hasn't seen any progress for " + silence.toSeconds() + " seconds. The watched thread is currently at:");
for (var element : watchedThread.getStackTrace()) {
System.err.println("\tat " + element);
}
}
try {
Thread.sleep(gracePeriod);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
while you can use as follows:
public class Test {
void step() throws Exception {
System.in.read();
}
void job() {
var snoopy = new Watchdog(Duration.ofSeconds(2));
for (;;) {
try {
step();
snoopy.everythingIsFine();
Thread.sleep(1000);
} catch (Throwable t) {
System.err.println(t);
}
}
}
public static void main(String[] args) throws Exception {
new Test().job();
}
}
once the grace period elapses, the WatchDog will print something like:
Watchdog hasn't seen any progress for 2 seconds. The watched thread is currently at:
at java.base/java.io.FileInputStream.readBytes(Native Method)
at java.base/java.io.FileInputStream.read(FileInputStream.java:293)
at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:255)
at java.base/java.io.BufferedInputStream.implRead(BufferedInputStream.java:289)
at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:276)
at stackoverflow.Test.step(Test.java:48)
at stackoverflow.Test.job(Test.java:55)
at stackoverflow.Test.main(Test.java:65)

Is it a good idea to close the JDBC connection in case of PG Listen/Notify polling?

We use connection pool in our application. While I understand that we should close and get connections as needed since we are using a connection pool. I implemented a cache update mechanism by receiving Postgres LISTEN notifications. The code is pretty much similar to the canonical example given by the documentation.
As you can see in the code, the query is initiated in the constructor and the connection is re used. This may pose problem when the connection is closed out of band due to any factor. One solution to this is to get the connection before every use, but as you can see the statement is only executed once in the constructor but still I can receive the notification in the polling. So if I get the connection every time, it will force me to re issue the statement for every iteration(after delay). I'm not sure if that's an expensive operation.
What is the middle ground here?
class Listener extends Thread
{
private Connection conn;
private org.postgresql.PGConnection pgconn;
Listener(Connection conn) throws SQLException
{
this.conn = conn;
this.pgconn = conn.unwrap(org.postgresql.PGConnection.class);
Statement stmt = conn.createStatement();
stmt.execute("LISTEN mymessage");
stmt.close();
}
public void run()
{
try
{
while (true)
{
org.postgresql.PGNotification notifications[] = pgconn.getNotifications();
if (notifications != null)
{
for (int i=0; i < notifications.length; i++){
//use notification
}
}
Thread.sleep(delay);
}
}
catch (SQLException sqle)
{
//handle
}
catch (InterruptedException ie)
{
//handle
}
}
}
In addition to this, there is also another similar document which had another query in run method as well in addition to constructor. I'm wondering if someone could enlighten me the purpose of another query within the method.
public void run() {
while (true) {
try {
//this query is additional to the one in the constructor
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1");
rs.close();
stmt.close();
org.postgresql.PGNotification notifications[] = pgconn.getNotifications();
if (notifications != null) {
for (int i=0; i<notifications.length; i++) {
System.out.println("Got notification: " + notifications[i].getName());
}
}
// wait a while before checking again for new
// notifications
Thread.sleep(delay);
} catch (SQLException sqle) {
//handle
} catch (InterruptedException ie) {
//handle
}
}
}
I experimented closing the connection in every iteration(but without getting another one). That's still working. Perhaps that's due to unwrap that was done.
Stack:
Spring Boot, JPA, Hikari, Postgres JDBC Driver (not pgjdbc-ng)
The connection pool is the servant, not the master. Keep the connection for as long as you are using it to LISTEN on, i.e. ideally forever. If the connection ever does close, then you will miss whatever notices were sent while it was closed. So to keep the cache in good shape, you would need to discard the whole thing and start over. Obviously not something you would want to do on a regular basis, or what would be the point of having it in the first place?
The other doc you show is just an ancient version of the first one. The dummy query just before polling is there to poke the underlying socket code to make sure it has absorbed all the messages. This is no longer necessary. I don't know if it ever was necessary, it might have just been some cargo cult that found its way into the docs.
You would probably be better off with the blocking version of this code, by using getNotifications(0) and getting rid of sleep(delay). This will block until a notice becomes available, rather than waking up twice a second and consuming some (small) amount of resources before sleeping again. Also, once a notice does arrive it will be processed almost immediately, instead of waiting for what is left of a half-second timeout to expire (so, on average, about a quarter second).

How can I create a continous For Loop within a Java program until a condition is met?

I wish to create a continuous Enhanced For loop within a Java program to output a message from an automatic ping to a Text area, and then to stop when a condition is met (IP address is offline). I have IP addresses in a String array called 'ip'. Works fine with no loop but requires continuous iterations until no response is detected.
Tried using Boolean loop which I included with the code - however does not append text to the TextArea and gets caught in a continuous loop.
for (String ip : listOfhosts) {
boolean repeatLoop = true;
try {
InetAddress i = InetAddress.getByName(ip);
textArea.append("Sending Ping Request to " + ip + "\n");
//boolean run = true;
//while (run){
if (i.isReachable(100)) { // 1 second limit
textArea.append("Host is online \n");
} else {
textArea.append("\nHOST IS OFFLINE\n");
//System.exit(0); //If something is offline, system will close. For now.
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("email#gmail.com"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("email#hotmail.com"));
message.setSubject("Test Mail");
message.setText("Test Mail," + "\n Sent From sendMail.java application\n");
//textArea.append("OK - Online \n");
Transport.send(message);
textArea.append("Mail Sent to email#email.com \n host " + ip + " is offline \n");
return;
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
} catch (Exception e) {
textArea.append("Unknown HOST\n");
e.printStackTrace();
}while(repeatLoop);
Gets caught in continuous loop - crashing the program. Any help would be great!
This code will block you UI. You should run it in a separate thread, and also add some delay between checks.
A simpler solution would also be to use a Timer
For instance, to check every second:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
// your code
}
}, 1000);
There're two simple ways to break out of an enhanced for-loop in Java. One is to throw an exception, although for normal flow control this is considered exceptionally poor use of exceptions.
The other is to use break; which will break you out of the most immediate for-loop. People aren't always fond of return mid-function or break mid-for loop (or continue for that matter) as they can act a bit like goto/jump statements and reduce the clarity of your code. On the other hand, this is exactly what break is intended for, so there's no argument about misuse of the instruction.
An alternative approach is to use a normal while loop and forgo the enhanced for-loop for a normal iterator. In this case, listOfHosts.iterator(), will allow you to calculate a combination of .hasNext() and isReachable(...) to decide whether to continue looping.
// suppose listOfhosts is a String Array
List<String> srcHostList = new ArrayList<String>();
srcHostList.addAll(Arrays.asList(listOfhosts));
List<String> offlineList = new ArrayList<String>();
while( srcHostList.size() > 0) {
offlineList.clear();
for(String ip: srcHostList) {
boolean isOnline = true;
try{
// TODO check online
}catch(Exception ex){
// TODO handle exception
isOnline = false;
}
if(!isOnline) offlineList.add(ip);
}
srcHostList.removeAll(offlineList);
}

java implementation : polling a web service

Please find below my requirement.
Requirement : Poll a web service. Two crucial parameters of polling max_timeout, polling_interval are configured in properties file. Overall objective is to spend for a time of overall in obtaining the response. If we get the response with in max_timeout, we can return the response to client. Otherwise we will throw an error saying that the operation is unsuccessful.
Below is the code snippet I have written.
int maxTimeOut = 10;
int interval = 2;
int iterations = maxTimeOut/interval;
boolean success = false;
for (int i = 0; i < iterations; i++)
{
System.out.println("Number of iteration = " + i);
try
{
Thread.sleep(interval * 1000);
System.out.println("Waited for " + interval + " seconds");
success = getWSResponse(i);
System.out.println("CALL" + ((success) ? "SUCCESSFUL" : "FAIL"));
if(success) break;
}catch (InterruptedException ie)
{
System.out.println(ie.getMessage());
}
}
//Send the success flag to client
Could you correct me if this is the proper implementation of polling. I am little bit concerned that this code assumes that webservice call returns in no time. If this takes 2-3 seconds (usually it does ), then we would be spending more than max_timeout overall for POLLING alone. How could we fix this. Is there any better approach than this.
you can combine the use of a ScheduledExecutorService with the HttpURLConnection-Timeout to poll in a given delay - and abort the task if it takes any longer.
If polling just means that the webservice is up and running, in your poll code you can try to open a connection to the webservice (with connection timeout) .If you are successfully able to connect, this means the webservice is up.
HttpURLConnection connection = null;
URL url = new URL("URL");
connection = (HttpURLConnection) url.openConnection();
connection .setConnectTimeout(timeout);//specify the timeout and catch the IOexception
connection.connect();
EDIT
Alternatively, you can call the webservice using an executor (see java.util.concurrent.ExecutorService) in a task with timeout and can decide accordingly. Sample :
// Make the ws work a time-boxed task
final Future<Boolean> future= executor.submit(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
// get ws result
return getWSResponse();
}
});
try {
boolean result = future.get(max_wait_time, TimeUnit.SECONDS);
} catch (TimeoutException te) {
throw e;
}

retry logic uptil databases comes up

Through my java code i m connecting to multiple databases using connection pooling.if my database goes down i need handle the retry logic to get connection until its return a connection object.
If your db connection throws some sort of an Exception then you can just sleep for a bit and retry the operation again.
In the example below worker is an object that does some work such as connecting to a db, etc. It's pretty generic so you can retry any sort of an operation such as reading from a file, etc.
Note that catching Throwable might not necessarily be a great idea.
boolean success = false;
int i = 0;
long delay = retryDelay;
LOGGER.info("Starting operation");
/*
* Loop until you cannot retry anymore or the operation completed successfully
* The catch block has a nested try catch to ensure that nothing goes wrong
* while trying to sleep
*
* In case of failure the last retry exception is propagated up to the calling
* class.
*/
while (i++ < retryMax && !success)
{
try
{
worker.work();
success = true;
}
catch (Throwable t)
{
try
{
LOGGER.warn("Caught throwable", t);
if (i == retryMax)
{
LOGGER.warn("Retry maximum reached, propagating error");
throw t;
}
if (retryPolicy == RetryPolicy.ESCALATING)
{
delay *= 2;
}
LOGGER.info("Sleeping for " + delay + " milliseconds");
Thread.sleep(delay);
}
catch (Throwable tt)
{
/*
* Quick check to see if the maximum has been hit, so we don't log twice
*
* t is the original error, and tt is the error we got while retrying
* tt would most likely be a InterruptedException or something
*/
if (i == retryMax)
{
throw t;
}
LOGGER.warn("Error while retrying, propagating original error up", tt);
throw t;
}
}
} // end retry loop

Categories

Resources