I have met something that I cannot explain to myself today. It was a small task on an online resource to write a program that will be run on some tests. Can you please explain me the difference between two methods and why one of them fails on some tests (I don't have them).
The task is to write a static method that opens a connection and then tries 3 times to do some abstract stuff with this connection by calling its method. The problem is that any method you use can throw an exception (open connection and connection method). You must try to do the stuff exactly 3 times (if all attempts failed - throw an exception) and another condition is that every opened connection must be closed.
The connection class called RobotConnection and it implements AutoCloseable. This class has method void moveRobotTo(int x, int y) (it is the "do stuff method" from the task). You can get instance of RobotConnection only by calling RobotConnectionManager.getConnection(). Methods of these classes can throw RobotConnectionException extends RuntimeException.
So the real question COMES HERE:
This code fails (no idea why, presumably infinite loop):
public static void moveRobot(RobotConnectionManager robotConnectionManager, int toX, int toY) {
boolean success = false;
for (int i = 0; !success && (i < 3); ++i) {
try (RobotConnection connection = robotConnectionManager.getConnection()) {
connection.moveRobotTo(toX, toY);
success = true;
}
}
if (!success) {
throw new RobotConnectionException("3 attempts failed");
}
}
And this one was accepted as working (I cannot see the real difference =( )
public static void moveRobot(RobotConnectionManager robotConnectionManager, int toX, int toY) {
boolean success = false;
for (int i = 0; !success && (i < 3); ++i) {
try (RobotConnection connection = robotConnectionManager.getConnection()) {
connection.moveRobotTo(toX, toY);
success = true;
} catch (RobotConnectionException e) {}
}
if (!success) {
throw new RobotConnectionException("3 attempts failed");
}
}
In your first method, you don't catch RobotConnectionException. Consequently, it can fail at most once, rather than the required exactly 3 times.
The difference is that in the first case, you say "open and clean up the connection, but I don't know how to deal with exceptions: let them propagate up the call chain to something which can handle it":
try (RobotConnection connection = robotConnectionManager.getConnection()) {
// ...
}
whereas in the second case, you say "open and clean up the connection, but if an exception occurs, I will deal with it myself; the action I will take is to do nothing":
try (RobotConnection connection = robotConnectionManager.getConnection()) {
// ...
} catch (RobotConnectionException e) {}
If a RobotConnectionException is thrown in the first code snippet, then it might come from inside the try statement. Since you do not catch it, you will not necessary make three attempts.
More information on java exceptions: http://docs.oracle.com/javase/tutorial/essential/exceptions/
Related
I made a switch case statement menu with one of the options being System.exit(0);. This is all surrounded by a try, finally that calls the method all of this is in. Would you guys not recommend this style of loop or am I all good?
public void Run() {
Scanner myObj = new Scanner(System.in);
int menuInput;
try {
System.out.println(" 1) call something\n"
+"2) quit");
menuInput = myObj.nextInt();
myObj.nextLine();
switch(menuInput) {
case 1:
something();
break;
case 2:
System.exit(0);
break;
}
}catch (Exeption e ){
System.out.println("Something went wrong.");
}finally{
Run();
}
}
No.
What you have here is an infinite recursion. Eventually you'd overflow the stack.
Use an actual loop instead:
while (true) {
try {
// ...
} catch (Exception e) {
// ...
}
}
And you almost never want to call System.exit. Just break the loop instead.
Is this legal code? Yes.
Is what you have there recommended? No.
If the method throws an exception it's likely recalling it will throw again. See the quote below.
Calling it again in a tight loop without attempting remedy, at least waiting a recovery and counting failures (3 strikes out?) will just end up in a tight loop of failure and stack overflow here.
So:
Can you identify errors that retrying may work and only retry on those?
You should almost certainly include some kind of 'back-off' wait before retry.
Always (always!) include a maximum retry number after which you accept failure.
In my experience the only kind of failure that may work on retry is 'service unavailable' meaning an intermittent outage.
It may not be relevant, but things like (say) invalid credentials aren't going to fix themselves and ideally you don't resubmit those. That's particularly because you end up locking the account and being in an even worse state and possibly causing issues for others using the valid credential...
The other scenario is (say) file not found and you're using the non-existence of a file as a way of polling for something.
That's a poor design pattern and is a misuse of exception handling.
You should strongly prefer to use some kind for existence check in those cases and not let routine activity get confused with exception handling of issues.
Also if you do retry log each attempt (it may be useful later to see whether things are running smoothly or getting delayed in retry scenarios even if the go through eventually). But always differentiate a 'Warning' when retrying and 'Error' when 'throwing in the towel' and failing.
public class Runner {
private static int MAX_RETRIES=3;
private static int BACK_OFF_MILLIS=30000;
public void Run() throws Exception,InterruptedException {
final int TRIES=3;//In reality may be configured.
int trycount=1;
for(;;){
try{
tryRun();
return;
}catch(Exception e){
String message=e.getMessage();
if(trycount>=MAX_RETRIES){
System.out.println("*FAILED*: "+e.getMessage());
throw e;
}
boolean retriable=true;
//Any tests for non-retriable exceptions here...
if(!retriable){
System.out.println("*FAILED*: non-retriable exception - "+e.getMessage());
throw e;
}
++trycount;
System.out.println("Warning: "+e.getMessage()+" retrying "+ trycount+" of "+TRIES);
try {
Thread.sleep(trycount*BACK_OFF_MILLIS);//Some kind of back-off...
}catch(InterruptedException ie){
System.out.println("*FAILED*: Interrupted. Aborting.");
throw ie;
}
continue;
}
}
}
public void tryRun() throws Exception{
//Real workload goes here!
}
}
NB: The back-off strategy here is very simplistic. When it comes to outages then it's usually recommended to implement a random element and an increasing back-off like 1 minute, 10 minutes, 25 minutes. But that's a topic in itself.
I'm not sure who really said but this popular quote seems relevant.
The definition of insanity is doing the same thing over and over again
and expecting different results
I have some class:
#Component
public MyClass {
private volatile boolean stopped = false;
public void verification() throws Exception {
Thread kpiAllThread = getKPIAllThread();
try {
for (int i = 0; i < poolSize; i++) {
execDispatcher.put(processExecutor.submit(getCheckValuesInKPIConsumerTask(workingQueue)));
}
kpiAllThread.start();
} finally {
waitFinished();
}
}
public void setStop(bolean stopped) {
this.stopped = stopped;
}
private Thread getKPIAllThread() {
return new Thread(() -> {
try {
LOG.debug("KPIAllThread started!");
dao.getKpiAll(workingQueue);
for (int i = 0; i < poolSize; i++) {
workingQueue.put(() -> true);
}
} catch (Exception ex) {
LOG.error("KPIAllThread exception: ", ex);
} finally {
LOG.error("KPIAllThread finished!");
}
});
}
}
This class starts the producer thread getKPIAllThread. He get data from db and put in BlockingQueue.
Method getKpiAll like this:
public void getKpiAll(final BlockingQueue<KeyPropertyIndex> kpiData) throws Exception {
LOG.debug("Starting getKpiAll");
try (final Connection con = dataSource.getConnection();
final Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) {
stmt.setFetchSize(Integer.MIN_VALUE);
try (final ResultSet rs = stmt.executeQuery(sqlGetAllkpi)) {
while (rs.next()) {
kpiData.put(new KeyPropertyIndexData(rs.getLong(1), rs.getString(2)));
}
}
LOG.debug("Finished get getKpiAll");
} catch (Exception ex) {
throw ex;
}
}
There is also a variable stopped that can be set from outside to true. How can I safely stop my thread while doing so? So that all connections to the database are closed and the thread is successfully completed?
The cleanest and safest rule for stopping a thread is that the code running in thread should periodically check a condition (say, boolean shouldExit()). When the code detects that this condition is true, it should stop doing what is doing and terminate.
The code running in thread should check this condition fairly often so that it can react reasonably fast. As a rule of thumb, the thread should exit less than one second after you set this condition. The check would typically look something like if (shouldExit()) break somewhere in your for-loop that iterates over pool size. However, dao.getKpiAll(workingQueue) looks potentially long, so you might place more checks inside getKpiAll.
When you have this checking in place, you must ensure that your code will exit cleanly every time the condition becomes true. For example, you can use finally blocks to close any connections etc. If this happens during getKpiAll, there is no sense to even continue with for loop to process items and so on.
Sometimes, this can get more tricky - i.e. when the thread is waiting on a network operation, you might need to close the network socket or something like that to interrupt it. In any case, avoid using Thread.stop() or Thread.interrupt() - see documentation why they are problematic.
If you do things like this, you can set the condition from outside the thread at any time to request the thread to terminate. You can make something like void requestExit() and set a boolean variable there. After calling requestExit(), you call Thread.join() with a suitable timeout to wait for the thread to do its business, check the condition and exit. Again, as a rule of thumb, make the timeout 3-10 times as long as the longest reaction time of your thread.
It looks that you already have setStopped(boolean stopped) for that purpose, but you're not checking it. First, I would remove parameter stopped because it doesn't make sense to pass false to it. Second, you need to add checks as described above. You might want to make this variable visible to dao - just remember that it's much better to expose it as a synchronized boolean method than as a boolean field.
I can't figure out why my code isn't compiling correctly.. I can go through the code till it gets to the catch block. It works, displaying the message, so I know it's catching the error. However, it ends my program saying I have that same error at the same place. I can't see what I am doing wrong. Thanks for any help!!
class Verification {
String detAccess(String[] pL, String[] uL, String pass, String user) {
int pos = 0;
String access = "";
try {
for (int i=0; !user.equals(uL[i]); i++)
pos++;
} catch (ArrayIndexOutOfBoundsException exec) {
System.out.println("Username doesn't exist.");
throw exec;
}
if(pass.equals(pL[pos])) {
access = "MEMBER";
} else {
System.out.println("Incorrect password.");
access = "DENIED";
}
return access;
}
}
You are rethrowing the exception - throw exec;
You should rewrite your code to something like this:
int pos = -1;
...
for (int i=0;uL.length; i++)
{
if(user.equals(uL[i])) { pos=i; break; }
}
...
if(pos==-1)
{
// user not found
} else {
// test the pass with pos as index
}
You're rethrowing the exception.
Another thing:
if(pass.equals(pL[pos])) {
access = "MEMBER";
That will cause the exception to come up again even if you didn't rethrow it as it'll try to check the password list with a nonexistent index.
you are throwing the exception back up. the point of handling the exception is that it wron't carry on.
Two problems:
You're catching and rethrowing the exception; if you "handle it", you don't need to rethrow it.
You're using "Exception Handling" to manage the "normal control flow" through your program. This is generally considered "bad style". Can you not control your iteration, and determine that "you're done" by looking something else?
UPDATE: i.e. nio's example
The code is compiling correctly if you're able to run it. As for the program ending in error, that's because you're throwing an exception:
throw exec;
You successfully caught the exception, but then you threw it again. If nothing else catches it, the program will terminate in an error.
Should last statement be return in and non void return types method? But this is still working.
public String test()
{
try
{
// Do my work
return "myValue";
}
finally
{
System.out.println("I'm in Finally");
}
}
I'm bit lack of knowledge to understand how this work. Could someone explain me.
There is no problem with this code, because every possible path through it inevitably leads to a return statement*. It does not have to be the last statement textually, as long as it is the last statement logically (Java compiler is smart enough to figure out if it's so, and give you an error if there are paths through your code that do not return a value or throw an exception). The fact that there will be code executing after hitting the return (i.e. your finally block) does not change anything: as far as the compiler is concerned, your function has provided a return value before exiting the function.
* In fact, there is only one path through your function's code, and it terminates at the return statement.
It is sufficient in Java to make sure that all possible code paths either return a value or throw an exception. For example, the following code is valid:
public boolean test() {
if (3 < 5) {
return true;
} else {
throw new RuntimeException("Holy crap!");
}
}
In your example, your try block ends with a return, so the happy path is covered and there is no need for code beyond the finally; in addition, any exceptions thrown in the try will propagate out of the method and will have no chance to reach the end of the method, so all possible paths will never hit the section under the finally block and no return statement is needed. (In fact, a compiler may give you a warning or error about unreachable code if you added a return statement at the bottom!)
Things change when you add a catch clause, because now it's possible for code to flow beyond the try/catch/finally block:
public String test(){
try{
// Do my work
return "myValue";
}
catch (Exception ex) {
System.out.println("O noes something went wrong");
// swallow exception
}
finally {
System.out.println("I'm in Finally");
}
// Oh no! If an exception was caught, code can actually flow through here.
// Compiler will complain about a missing return statement until you add one.
// return "someOtherValue";
}
The key JLS concept for this is Normal and Abrupt Completion of Statements, combined with the behavior of try-finally.
The try block completes abruptly because of the return of "myValue". The finally block completes normally, so the whole try statement completes abruptly due to the same cause as the try block, return of "myValue".
In effect, the last statement in the method, the try statement, is one that returns a String.
In this case try and finally always execute. So, it doesn't matter where is return.
public String myfun(){
return "here";
}
or
public String myfun(){
try{
return "here";
}finally{
//will execute always
}
}
Are almost same. When, you see the flow of program. But, if there would be any conditional like
public String myfun(){
if(x==1){
return "here";
}
else{
// something here
}
}
In this case, it will raise error. Since, either any of the block will execute not both. Same as
public String fun(){
try{
return "here";
}
catch(Exception e){
//catch implementation without return
}
}
I guess there isn't necessarily a 'right' answer to this, perhaps it's more a question of style but I often find myself wondering how to structure try/catch blocks.
For example take the two methods outlined in my hypothetical piece of code below (purely illustrative), I have a method that throws exceptions that I call multiple times but require different handling depending on which call it is. Similarly there could be different types of exception thrown with different handlers.
private Object exceptionMethod() throws Exception {
throw new Exception("Something bad happened");
}
public void useMethodSequentialHandlers() {
Object o1; // Must be declared in a wider scope than where it is used
try {
o1 = exceptionMethod();
} catch (Exception ex) {
// Assume we cannot continue after this exception so we'll return or
// rethrow to exit the method
return;
}
Object o2; // Must be declared in a wider scope than where it is used
// Do something that requires o1
for (int i = 0; i < 100; i++) {
try {
o2 = exceptionMethod();
// Here we would use the objects in some manner
boolean equal = o1.equals(o2);// Just a pointless example
// to show that both objects
// are required
// Assume the method does a load of stuff down here
} catch (Exception ex) {
// Assume we can continue to the next iteration after this exception
continue;
}
}
}
As I see it the advantage of having the try/catch blocks in a sequential order is that it is clearer to the reader exactly at what point I'm responding to the exception so perhaps there is better code clarity.
The disadvantages would be that we have exception handling littered around various places in the method and we have variables declared in a wider scope than required (is this a bad thing?).
Alternatively:
public void useMethodNestedHandlers() {
try {
Object o1 = exceptionMethod(); // Can be declared inside scope where it is used
// Do something that requires o1
for (int i = 0; i < 100; i++) {
try {
Object o2 = exceptionMethod(); // Can be declared inside scope where it is used
// Here we would use the objects in some manner
boolean equal = o1.equals(o2); // Just a pointless example
// to show that both objects
// are required
// Assume the method does a load of stuff down here
} catch (Exception ex) {
// Assume we can continue to the next iteration after this
// exception
continue;
}
}
} catch (Exception ex) {
// Assume we cannot continue after this exception so we'll return or
// rethrow to exit the method
return;
}
}
Here we keep exception handling logic together and variables are declared within the scope they're used. However to me the exception handling logic seems less clear as it is further from it's point of origin.
Does anyone have an opinion on which would be better or am I just worrying about pointless minutiae and should just get on with my job? :-)
Thanks
I would prefer both depends the condition.
Case 1
Object obj;
try {
// do something
} catch (Exception e) {
obj = default_obj; // assign default object
}
try {
// do something either with specific or default object
} catch (Exception e) {
// handle exception
}
Here even if the first try catch fails , proceed the action with default value
Case 2
try {
Object obj;
// acquire object
// do something only if acquire object is successful
} catch (Exception e) {
// handle exception
}
Here do not proceed further when acquire object isn't successful.
Here it is way of handling exception is more of a necessity than a style.
I believe that in all cases were the answer does not clearly arise from technical analysis one should ignore the initial development work and study the future of the code.
To this end I would advise the first method as the best choice unless there is a real technical reason to choose the second.
In summary:
If there is no technical difference between two styles, consider the future reader of your code and make it as obvious as possible.
The beauty of exceptions is that you don't have to handle them where they occur. That's why you should in fact use your second style, but without the outer try-catch:
public void useMethodNestedHandlers() {
Object o1 = exceptionMethod(); // Can be declared inside scope where it is used
// Do something that requires o1
for (int i = 0; i < 100; i++) {
try {
Object o2 = exceptionMethod(); // Can be declared inside scope where it is used
// Here we would use the objects in some manner
boolean equal = o1.equals(o2); // Just a pointless example
// to show that both objects
// are required
// Assume the method does a load of stuff down here
} catch (Exception ex) {
// Assume we can continue to the next iteration after this
// exception
continue;
}
}
}
Code for the happy-day scenario and let someone else worry about failures. That's the way to achieve separation of concerns: usually all failures are treated by the same piece of code and catching too early breeds duplicated code.
the code should be 1) correct, 2) readable. usually all irrecoverable exception should be handle in highest layer of application (or not at all). that means they should be properly displayed to the user. all recoverable exceptions should be handle 'as high' as possible. i advise to use as few try-catch statements as possible