Delaying an exception - java

I have a method that periodically (e.g. once in every 10 secs) try to connect to a server and read some data from it. The server might not be available all the time. If the server is not available the method throws an exception.
What would be the best way to implement a wrapper method that doesn't throw an exception except if the server wasn't available for at least one minute?

Keep track of when the last time you successfully reached the server was. If the server throws an exception, catch it and compare to the last time you reached the server. If that time is more than a minute, rethrow the exception.

In pseudocode.
//Create Timer
//Start Timer
bool connected = false;
while (!connected)
try {
//Connect To DB
connected = true;
}
catch (Exception ex) {
if (more than 1 minute has passed)
throw new Exception(ex);
}
}

You will have to record the time that you originally try to connect to the server and then catch the exception. if the time that the exception is caught is more than the original time + 1 minute, rethrow the exception. If not, retry.

Ideally you can put a timeout on the call to the server. Failing that do a thread.sleep(600) in the catch block and try it again and fail if the second one doesn't return.

Remember that exception handling is just a very specialized use of the usual "return" system. (For more technical details, read up on "monads".) If the exceptional situation you want to signal does not fit naturally into Java's exception handling system, it may not be appropriate to use exceptions.
You can keep track of error conditions the usual way: Keep a state variable, update it as needed with success/failure info, and respond appropriately as the state changes.

You could have a retry count, and if the desired count (6 in your case) had been met then throw an exception
int count = 0;
CheckServer(count);
public void CheckServer(count) {
try
{
// connect to server
}
catch(Exception e)
{
if(count < MAX_ATTEMPTS) {
// wait 10 seconds
CheckServer(count++)
}
else {
throw e;
}
}
}

You can set a boolean variable for whether or not the server connection has succeeded, and check it in your exception handler, like so:
class ServerTester : public Object
{
private bool failing;
private ServerConnection serverConnection;
private Time firstFailure;
public ServerTester(): failing(false)
{
}
public void TestServer() throws ServerException
{
try
{
serverConnection.Connect();
failing = false;
}
catch (ServerException e)
{
if (failing)
{
if (Time::GetTime() - firstFailure > 60)
{
failing = false;
throw e;
}
}
else
{
firstFailure = Time::GetTime();
failing = true;
}
}
}
}
I don't know what the actual time APIs are, since it's been a while since I last used Java. This will do what you ask, but something about it doesn't seem right. Polling for exceptions strikes me as a bit backwards, but since you're dealing with a server, I can't think of any other way off the top of my head.

Related

Preventing java.lang.StackOverflow error simple sql pool

so I am running multiple sql calls and I have a custom 'sql pool' of connections, however it's starting to send java.lang.stackoverflow errors. How would I go about preventing this. Here's my current code.
public static synchronized PooledSqlConnection getConnectionFromPool() {
for(PooledSqlConnection connection : pooledSqlConnections) {
if(connection.getConnection() == null) {
connection.setUpConnection();
}
if(!connection.isInUse()) {
connection.setInUse(true);
return connection;
}
}
return getConnectionFromPool();
}
Would something like this work well?
public static synchronized PooledSqlConnection getConnectionFromPool() {
boolean foundPool = false;
while(!foundPool) {
for(PooledSqlConnection connection : pooledSqlConnections) {
if(connection.getConnection() == null) {
connection.setUpConnection();
}
if(!connection.isInUse()) {
connection.setInUse(true);
foundPool = true;
return connection;
}
}
}
return null;
}
Every time a connection is used, it's marked as in-use, once it's finished it marks it as not in use.
Your decision to make a recursive call when you fail to find an available connection doesn't seem like a good idea. When you run out of available connections, it causes infinite recursion and StackOverflowError.
Instead of the recursive call, you can wrap your for loop with another for loop that would sleep after each iteration of the inner loop (to give the occupied connections time to be released).
Or, as an alternative, throw an exception if there are no available connections. This will make it the responsibility of the caller of getConnectionFromPool() to retry when an exception is thrown.
It seems pretty likely that the stack overflow is caused by the recursive call to getConnectionFromPool(). To avoid it, you want to derecursify your method, as follows:
public static synchronized PooledSqlConnection getConnectionFromPool() {
while (true) {
for(PooledSqlConnection connection : pooledSqlConnections) {
if(connection.getConnection() == null) {
connection.setUpConnection();
}
if(!connection.isInUse()) {
connection.setInUse(true);
return connection;
}
}
// If we reach this stage, there is no available connection.
// FIXME: Add some form of sleep and/or wait
// to be notified once a connection is available.
}
}
Note I don't know enough about PooledSqlConnection to be sure that this snippet fully works.

What can I do to resolve the connection issue?

I have an app that uses JSoup to connect to a web server, and it works fine. Unfortunately, the said web server isn't very reliable. I get SocketException because of time-out connection quite often. I make the connection in a modified IntentService, and I just simply repeat onHandleIntent(intent) in the catch(Exception e) block.
catch(Exception e){
Log.d(Tag, "in catch Exception block...");
onHandleIntent(intent);
}
Theoretically, this should work. But sometimes, I get stack over flow error, and the app ended quite ungracefully. So, what can I do to make it better?
I want to continue to call onHandleIntent, so, maybe I have to call it in iteration instead of recursively. If you can give me advice on how to implement this iteratively, it would be very helpful. Thanks!
I want to continue to call onHandleIntent, so, maybe I have to call it in iteration instead of recursively.
That is correct. If you handle this recursively, a server that continually times out will inevitably result in a stack overflow.
If you can give me advice on how to implement this iteratively, it would be very helpful. Thanks!
Something like this:
for (int tries = 1; ; tries++) {
Connection conn = null;
try {
// attempt to connect
// do stuff
} catch (SocketException ex) {
if (/* timed out */ && tries < MAX_TRIES) {
continue;
}
// report exception
} finally {
if (conn != null) {
// close it
}
}
break;
}
(Maybe someone can think of a less "clunky" way to write this ...)

How can I catch an exception in an enhanced for loop and restart the process for this loop?

I have started working with enhanced for loops due to it's best practices and habilities to work with ArrayLists.
My code basically gets an ArrayList that contains links to songs and parses this list downloading the songs. One of the exceptions thrown is the TimeoutException, whitch normally happens when the server is overloaded or there's an instability with the internet connection.
To clarify:
try
{
for(Track track : album.getTracks())
{
songdown.downloadTrack(track, directorio, formataudio);
}
}
catch (TimeoutException te)
{
System.out.println("Timeout!");
}
track is an ArrayList whitch is parsed one by one by the songdown.downloadTrack function. When a download fails, a TimeoutException is raised, but I don't know how to treat this exception in order to delete the file I have generated and restart the for statement from the same track, so that the download can happen again.
While it's an open question how advisable this would be, you'd be better off with an inner loop that retries until successful. Something like this:
for (Track track : album.getTracks()) {
boolean downloaded = false;
while (!downloaded) {
try {
songdown.downloadTrack(track, directorio, formataudio);
downloaded = true;
} catch (TimeoutException te) { /* delete partially downloaded song etc */ }
}
}
You'd likely want a max # of retries within each iteration of the for loop or some other additional checks to avoid infinite looping.
There are surely many valid approaches.
Here's one possibility:
int failureCount = 0;
while (failureCount < maxFailures) {
try {
parseAndDownload(someList);
break;
}
catch (Exception ex) {
failureCount ++;
}
}
Please go through this first. First thing is that the catch block should start once the try block is done.
You can catch the exception in the catch block, and write the code which you want to get executed, when the exception occurs, which in you case is starting over again, and deleting the half downloaded songs.
Here is a snippet example, I think you can solve your problem by following this way
ArrayList<String> a = new ArrayList<String>();
a.add("a");
a.add("w");
a.add("d");
//Iterator<String> i = a.iterator();
for(String s:a){
try{
if(s.equals("w")){
throw new Exception("Hello");
}else{
System.out.println(s);
}
}catch (Exception e) {
continue;
}
}
In this snippet, I have explicitly throw an Exception, when it is thrown the catch block will execute, there i have used the keyword continue. This keyword is designed to tackle these kind of situation.

NetBeans / Java / New hint: Thread.sleep called in loop

In NetBeans, there's a new hint that says: Thread.sleep called in loop.
Question 1: How/when can it be a problem to sleep in a loop?
Question 2: If it's a problem, what should I do instead?
UPDATE: Question 3: Here's some code. Tell me in this case if I should be using something else instead of Thread.Sleep in a loop. In short, this is used by a server which listens for client TCP connections. The sleep is used here in case the max number of sessions with clients is reached. In this situation, I want the application to wait until a free session becomes available.
public class SessionManager {
private static final int DEFAULT_PORT = 7500;
private static final int SLEEP_TIME = 200;
private final DatabaseManager database = new DatabaseManager();
private final ServerSocket serverSocket = new ServerSocket(DEFAULT_PORT);
public SessionManager() throws IOException, SQLException
{
}
public void listen()
{
while (true)
if (Session.getSessionCount() < Session.getMaxSessionCount())
try
{
new Thread(new Session(database, serverSocket.accept())).start();
}
catch (IOException ex) { ex.printStackTrace(); }
else
try
{
Thread.sleep(SLEEP_TIME);
}
catch (InterruptedException ex) { ex.printStackTrace(); }
}
public static void main(String[] args) throws IOException, SQLException
{
new SessionManager().listen();
}
}
Calling sleep in a loop typically leads to poor performance. For example:
while (true) {
if (stream.available() > 0) {
// read input
}
sleep(MILLISECONDS);
}
If MILLISECONDS is too large, then this code will take a long time to realize that input is available.
If MILLISECONDS is too small, then this code will waste a lot of system resources check for input that hasn't arrived yet.
Other uses of sleep in a loop are typically questionable as well. There's usually a better way.
If it's a problem, what should I do instead?
Post the code and maybe we can give you a sensible answer.
EDIT
IMO, a better way to solve the problem is to use a ThreadPoolExecutor.
Something like this:
public void listen() {
BlockingQueue queue = new SynchronousQueue();
ThreadPoolExecutor executor = new ThreadPoolExecutor(
1, Session.getMaxSessionCount(), 100, TimeUnit.SECONDS, queue);
while (true) {
try {
queue.submit(new Session(database, serverSocket.accept()));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
This configures the executor to match the way your code currently works. There are a number of other ways you could do it; see the javadoc link above.
As others have said it depends on the usage. A legitimate use would be a program that is designed to do something every 10 seconds (but is not so critical that exact timing is needed). We have lots of these "utility apps" that import data and other such tasks every few minutes. This is an easy way to perform these tasks and we typically will set the sleep interval to be very low and use a counter so that the program stays responsive and can exit easily.
int count = 0;
while (true) {
try {
// Wait for 1 second.
Thread.sleep(1000);
}
catch (InterruptedException ex) {}
// Check to see if the program should exit due to other conditions.
if (shouldExit())
break;
// Is 10 seconds up yet? If not, just loop back around.
count++;
if (count < 10) continue;
// 10 seconds is up. Reset the counter and do something important.
count = 0;
this.doSomething();
}
I think I come across one completely legitimate use of sleep() method in loop.
We have one-way connection between server and client. So when client wants to achieve asynchronous communication with server, he sends message to the server and than periodically polls for some response from server. There needs to be some Timeout interval.
Response resp = null;
for (int i = 0; i < POLL_REPEAT && resp == null; i++) {
try {
Thread.sleep(POLL_INTERVAL);
} catch (InterruptedException ie) {
}
resp = server.getResponse(workflowId);
}
POLL_REPEAT * POLL_INTERVAL ~ TIMEOUT interval
How/when can it be a problem to sleep in a loop?
People sometimes employ it in place of proper synchronization methods (like wait/notify).
If it's a problem, what should I do instead?
Depends on what you're doing. Although it's dificult for me to imagine situation where doing this is the best approach, I guess that's possible too.
You can check Sun's concurrency tutorial on this subject.

How to make a try-catch block that keeps on calling a method on an object until there are no more exceptions to catch

Basically iterating through a list and,
- Invoke method on first object
- Catch the first exception (if any); if there are no more exceptions to catch, return normally. Otherwise, keep on invoking method until all exceptions are caught.
- Move on to next object.
I can iterate through each object, invoke the method, and catch one exception but I do not know how to continuously invoke the method on it and keep on catching exceptions.
This is similar to the other answers, but without the flag, which seems like clutter to me. I don't really understand the question though, so I'm just throwing it out there in case it is useful.
for (Item item : items) {
while (true) {
try {
item.doSomething();
break;
} catch (MyException ex) {
log.warn("Something failed.", ex);
}
}
}
This approach hinges on the operation of the unlabeled break statement, which completes abruptly and then exits the enclosing while statement normally.
Based on subsequent comments, I think there is some confusion about what it means when there are multiple exceptions declared to be thrown by a method.
Each invocation of a method can be terminated by just one exception being thrown. You can't somehow resume invocation where it left off, and handle subsequent exceptions.
So, if a method throws multiple exceptions, catch a common ancestor, and move on. For example, if a method throws java.io.EOFException or java.nio.channels.ClosedChannelException, you could simply catch java.io.IOException since it is a common ancestor. (You could also catch java.lang.Exception or java.lang.Throwable for the same reason.) Invoking the method again under the same conditions won't get you any further.
If you want to attempt to invoke the method on each object, even if some fail, use this:
for (Item item : items) {
try {
item.doSomething();
} catch (Exception ex) { /* This could be any common ancestor. */
log.warn("Something failed.", ex);
}
}
If you're talking about dealing with a single method call that will throw more than one exception, it can't be done -- no matter how many times you call the method, it will keep on throwing the first exception. You can't go back into the method and keep running from there; after throwing one exception, it's all over.
But if you're talking about a method that sometimes throws exceptions and sometimes doesn't, try something like this:
boolean thrown = false;
do {
try {
thrown = false;
method();
}
catch (Exception e) {
thrown = true;
// Handle as you like
}
} (while thrown);
This is what I understand.
You have an object's method which may throw a number of exceptions.
What you want to do is to catch them all and continue with the next object in the list.
Is that correct?
So, that would be:
for( YourObject o : yourList ) {
try {
o.thatMethod();//invoke that risky method
} catch( SomeExceptionClass sec ) {
// Do something with that exception
} catch( SomeOtherExceptionClass soec ) {
// Do something with that exception
} catch( YetAnotherxceptionClass yaec ) {
// Do something with that exception
} catch( OtherUnRelatedException oue ) {
// Do something with that exception
}
}
When you do this, if the invocation of thatMethod() throws an exception and that exception is listed in the catch section, the execution flow will jump to that exception and after it will continue to the normal flow ( which is the for loop and will continue with the next object )
I hope this is what to need. For more information read: The catch block in the Java Tutorial section Essential classes
I'm assuming that you are trying to performs some kind of validation to the items in a list, where the validation errors are reported by throwing exceptions. I'm also assuming that you are trying to collect all of the validation errors.
The simple answer is that this problem cannot be solved using this approach. To understand why, take a look at this:
boolean exceptionCaught = false;
do {
try {
item.doSomething();
} catch (MyException e) {
exceptionCaught = true;
}
} while (exceptionCaught);
This fails because each time you call item.doSomething() it is going to throw an exception at exactly the same place. The net result is an infinite loop.
The best you can do with this approach is to capture the first exception for each item in the list.
So how can you achieve what you are trying to achieve? The answer is that you have to change the validation code to use some other way to report errors than throwing exceptions. For example, you could change:
class Item {
...
void validate() {
if (noHat) {
throw new MyException("bad hat");
}
if (noPants) {
throw new MyException("world-wide pants");
}
}
}
to something like this:
class Item {
...
void isValid(List<MyException> errors) {
boolean ok = true;
if (noHat) {
errors.add(new MyException("bad hat"));
ok = false;
}
if (noPants) {
errors.add(new MyException("world-wide pants"));
ok = false;
}
return ok;
}
}
Messy huh! You could sugar this in various ways, but this style of error reporting is always going to be more complicated. But I don't think there is a practical way to avoid the messiness AND capture ALL of the validation errors.

Categories

Resources