'finally block does not complete normally' Eclipse warning - java

Eclipse give me that warning in the following code:
public int getTicket(int lotteryId, String player) {
try {
c = DriverManager.getConnection("jdbc:mysql://" + this.hostname + ":" + this.port + "/" + this.database, this.user, this.password);
int ticketNumber;
PreparedStatement p = c.prepareStatement(
"SELECT max(num_ticket) " +
"FROM loteria_tickets " +
"WHERE id_loteria = ?"
);
p.setInt(1, lotteryId);
ResultSet rs = p.executeQuery();
if (rs.next()) {
ticketNumber = rs.getInt(1);
} else {
ticketNumber = -1;
}
ticketNumber++;
p = c.prepareStatement(
"INSERT INTO loteria_tickets " +
"VALUES (?,?,?,?)");
p.setInt(1, lotteryId);
p.setInt(2, ticketNumber);
p.setString(3, player);
p.setDate(4, new java.sql.Date((new java.util.Date()).getTime()));
p.executeUpdate();
return ticketNumber;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (c != null) {
try {
c.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return -1;
}
}
What is wrong with my code?

remove return statement from it.
Final block is considered to be cleanup block, return is not generally expected in it.

The return from finally "overrides" further exception throwing.
public class App {
public static void main(String[] args) {
System.err.println(f());
}
public static int f() {
try {
throw new RuntimeException();
} finally {
return 1;
}
}
}
1

Generally a finally block should never have a return statement because it would overwrite other return-statements or Exceptions.
For further reading and more detailed answers to the backgrounds of it please see the question
Behaviour of return statement in catch and finally

With both return and throw statement in the finally bloc you will get the warning, for example, you will get the same warning with the following finally block:
...
}finally{
throw new RuntimeException("from finally!");
}
...

If you don't have any catch blocks, then your finally blocks have to be nested directly inside of each other. It's only catching an exception that allows your code to continue past the end of a try/catch/finally block. If you don't catch the exception, you can't have any code after a finally block!
You can see how this works with this example on Repl.it
Example Output
testing if 0 > 5 ?
try1
try2
finally3
catch1
finally2
After other finally
finally1
end of function
testing if 10 > 5 ?
try1
try2
try3
success
finally3
finally2
finally1
Code in example at Repl.it
class Main {
public static void main(String[] args) {
isGreaterThan5(0);
isGreaterThan5(10);
}
public static boolean isGreaterThan5(int a)
{
System.out.println();
System.out.println("testing if " + a + " > 5 ?");
try
{
System.out.println("try1");
try
{
System.out.println("try2");
try
{
if (a <= 5)
{
throw new RuntimeException("Problems!");
}
System.out.println("try3");
System.out.println("success");
return true;
}
finally
{
System.out.println("finally3");
}
}
catch (Exception e)
{
System.out.println("catch1");
}
finally
{
System.out.println("finally2");
}
System.out.println("After other finally");
}
catch (Exception e)
{
System.out.println("failed");
return false;
}
finally
{
System.out.println("finally1");
}
System.out.println("end of function");
return false;
}
}

Related

This method throws two different exceptions. How could man catch the two exceptions and prints exception catched for both exception types to console?

public class CatchingExceptions {
private int erroneousMethod(int p) {
if (p == 0) {
throw new IllegalArgumentException();
}
int x = 0x01;
return p / (x >> Math.abs(p)); // this line will throw!
}
The task is to implement the following method to catch and print the two exceptions.
public void catchExceptions(int passthrough) {
erroneousMethod(passthrough); // will throw!
try{
????
} catch (IllegalArgumentException e){
System.out.println("???? ");
}
}
Call the method inside the try block:
public void catchExceptions(int passthrough) {
try{
erroneousMethod(passthrough);
} catch (RuntimeException e) { // catches all unchecked exceptions
String message = e.getMessage() == null ? "" : (": " + e.getMessage());
System.out.println(e.getClass().getSimpleName() + ": " + message);
}
}

Missing return statement, what i am missing

I written a method which will acknowledge the controller by returning true and false, I return true inside try if everything goes fine it will return true and I return false inside catch blocks, but still method shows me error "missing return statement" what is the best way to do it.
The below method written in java will send back the true or false to the controller.
Secondly I want to carry the exception message from here to controller, I think of returning string, is it good approach,
Kindly suggest me the best way to do the exception handling
public boolean pickSalayData(String yearMonth, String regionId, String circleId, Userdetail loginUser) throws MyExceptionHandler {
String tableSuffix = yearMonth.substring(4, 6) + yearMonth.substring(0, 4);
log.info("Pick Salary Data From ERP " + DateUtility.dateToStringDDMMMYYYY(new Date()));
List<SalaryDetailReport> detailReports = hRMSPickSalaryDataDAO.findAll(yearMonth, regionId, circleId);
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus trstatus = transactionManager.getTransaction(def);
try {
List<SalaryDetailReport> salaryDetailReport = null;
int countDetail = 0;
if (detailReports != null && detailReports.size() > 0) {
for (SalaryDetailReport salary : detailReports) {
try {
if (countDetail % COMMIT_COUNT == 0) {
if (salaryDetailReport != null) {
salaryDetailReportDAO.save(salaryDetailReport, tableSuffix);
reportHistoryDAO.save(salaryDetailReport, loginUser);
}
salaryDetailReport = new ArrayList<SalaryDetailReport>();
}
salaryDetailReport.add(salary);
countDetail++;
} catch (Exception e) {
log.error("Error on Save Salary Pay Head Details Data from ERP to Prayas .");
}
}
if (salaryDetailReport != null && salaryDetailReport.size() > 0) {
salaryDetailReportDAO.save(salaryDetailReport, tableSuffix);
reportHistoryDAO.save(salaryDetailReport, loginUser);
}
} else {
throw new MyExceptionHandler("No record for Save in Database from ERP.");
}
salaryDetailReportDAO.update(tableSuffix, regionId, circleId);
List<SalaryDetailReport> reports = salaryDetailReportDAO.findAll(tableSuffix, regionId, circleId);
if (reports != null && reports.size() > 0) {
for (SalaryDetailReport salaryDetail : reports) {
try {
SalaryDetail sd = new SalaryDetail();
sd.setDetailReport(salaryDetail);
salaryDetailDAO.save(sd, tableSuffix);
} catch (Exception e) {
log.error("Error occured", e);
e.printStackTrace();
throw new MyExceptionHandler(" Error :" + e.getMessage());
}
}
System.out.println("data found");
} else {
log.error("Salary Record Not Found.");
throw new MyExceptionHandler("No record Found.");
}
salaryDetailDAO.updateEarningDeduction(tableSuffix);
//salaryDetailDAO.updateEarningDeductionsInSDT();
transactionManager.commit(trstatus);
try {
hRMSPickSalaryDataDAO.update(regionId, circleId, yearMonth);
return true;
} catch (Exception ex) {
log.error("Some error : ", ex);
}
// // System.out.println("Completed =============================");
} catch (MyExceptionHandler ex) {
transactionManager.rollback(trstatus);
ex.printStackTrace();
log.error("Failed to Save Salary data :" + ex.getMessage());
return false;
} catch (Exception ex) {
transactionManager.rollback(trstatus);
ex.printStackTrace();
log.error("Error occured on Save Salary data.", ex);
return false;
}
}
You are missing return statement for the following catch block :
catch (Exception ex) {
log.error("Some error : ", ex);
}
Either you add return statement in this catch block or at the end of mehtod
If this code throws an Exception, then the following catch code will not be entered into and hence there is no return value
try {
hRMSPickSalaryDataDAO.update(regionId, circleId, yearMonth);
return true;
} catch (Exception ex) {
log.error("Some error : ", ex);
**edit**
return `true||false`;
}
} catch (...) {
return something;
}

What happens when both catch block and finally block throw exception in Java?

Consider this question I was asked in an interview
public class Test_finally {
private static int run(int input) {
int result = 0;
try {
result = 3 / input;
} catch (Exception e) {
System.out.println("UnsupportedOperationException");
throw new UnsupportedOperationException("first");
} finally {
System.out.println("finally input=" + input);
if (0 == input) {
System.out.println("ArithmeticException");
throw new ArithmeticException("second");
}
}
System.out.println("end of method");
return result * 2;
}
public static void main(String[] args) {
int output = Test_finally.run(0);
System.out.println(" output=" + output);
}
}
Output of this program throws ArithmeticException not UnsupportedOperationException
Interviewer simply asked how will i let the client know the original exception raised was of type UnsupportedOperationException not ArithmeticException.
I didn't know that
Never return or throw in a finally block. As an interviewer i would expect that answer.
A crappy interviewer looking for a minor technical detail might expect you know Exception.addSuppressed(). You can not actually read the thrown exception in a finally block so you need to store it in the throw block to reuse it.
So something like that:
private static int run(int input) throws Exception {
int result = 0;
Exception thrownException = null;
try {
result = 3 / input;
} catch (Exception e) {
System.out.println("UnsupportedOperationException");
thrownException = new UnsupportedOperationException("first");
throw thrownException;
} finally {
try {
System.out.println("finally input=" + input);
if (0 == input) {
System.out.println("ArithmeticException");
throw new ArithmeticException("second");
}
} catch (Exception e) {
// Depending on what the more important exception is,
// you could also suppress thrownException and always throw e
if (thrownException != null){
thrownException.addSuppressed(e);
} else {
throw e;
}
}
}
System.out.println("end of method");
return result * 2;
}

A `try catch //this is a workaround` in the method. How should it be rewrtten?

A project source code has a Java method for SQL handling. The method does work, but it uses a questionable workaround: try-catch block at the very end of the method for normal execution. What is the correct way to implement it?
public void run() {
if (running) {
return;
}
running = true;
while(null == Common.server || null == Common.database || !ConnectionsPool.isInitialized()) {
// Wait until the database is set before continuing...
try {
Thread.sleep(1000);
}
catch(Exception ex) {}
}
while(running) {
final Connections cs = ConnectionsPool.getConnections();
Connection c = null;
while(!entries.isEmpty()) {
if (null == c) {
c = cs.getConnection();
}
SQLLogEntry entry = entries.remove();
if (null != entry) {
try {
write(entry, c); //find usages
}
catch (SQLException ex) {
writeLogFile("Could not write entry to SQL", ex);
}
}
}
if (null != c) {
try {
c.commit();
}
catch (SQLException ex) {
writeLogFile("Could commit to SQL", ex);
try {
c.rollback();
}
catch (SQLException ex1) {
}
// log
final StringWriter err = new StringWriter();
ex.printStackTrace(new PrintWriter(err));
EditorTransactionUtil.writeLogFile(err.toString());
// for user
final String msg = "Exception: " + EditorUtil.getErrorMessage(ex.getMessage());
try {
SwingUtilities.invokeAndWait(() -> {
JOptionPane.showMessageDialog(null, msg);
});
}
catch (Throwable ex1) {
}
}
finally {
cs.returnConnection(c);
}
c = null;
}
synchronized(entries) {
try {
entries.wait(1000);
}
catch (InterruptedException ex) {
// This is a workaround to process this loop...
}
}
}
writeLogFile("SQLMsgLogger run loop stopping...");
}
Problems with this code start here.
If(running) return;
running=true;
This is clearly an attempt to make sure that only one thread executes. This is a wrong way to check concurrency. Second tread might kick in right when if check ended, but assignment didn't start yet. You need to use syncronizible interface.
As for the disposed try catch block - as Konrad pointed out it will not be executed without Thread.interrupt() call. It might be dead code left from previous versions.

Exception handling makes code logic unclear

I had the following code, which is responsible for assigning roles and groups to users.
private void override(List<Assignment> assignments) {
removeAll();
addMultiple(assignments);
}
protected void removeAll() {
removeAllRoles();
removeAllGroups();
}
private void removeAllGroups() {
Iterator<String> userGroups = user.getParentGroups(false);
while (userGroups.hasNext()) {
UMHelper.removeUserFromGroup(user.getUniqueID(), userGroups.next());
}
}
private void addMultiple(List<Assignment> assignments) {
for (Assignment assignment : assignments) {
add(assignment);
}
}
public static void addUserToGroup(String userId, String groupId) {
try {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Trying to add user " + userId + " to group " + groupId);
groupFactory.addUserToGroup(userId, groupId);
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Success");
} catch (UMException e) {
SimpleLogger.traceThrowable(Severity.ERROR, loc, "Addition failed", e);
}
}
I hope the logic is pretty clear. Most of the code is iteration over collections. Adding a user to role or group can cause exception, which I report in log.
Since I find it not good to suppress exceptions and because a client calling override method should know the result of assigment, I rewrote the code adding exception handling. The execution should continue, even if some assignments failed.
private void override(List<Assignment> assignments) {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Override was started with " + assignments.size() + " assignments");
try {
removeAll();
} catch (UMException e) {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Removing all existing elements failed");
}
try {
addMultiple(assignments);
} catch (UMException e) {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Adding new elements failed");
}
}
protected void removeAll() throws UMException {
boolean successfulRemoval = true;
try {
removeAllRoles();
} catch (UMException e) {
successfulRemoval = false;
}
try {
removeAllGroups();
} catch (UMException e) {
successfulRemoval = false;
}
if (!successfulRemoval){
throw new UMException("Not all user elements could be removed");
}
}
private void removeAllGroups() throws UMException {
boolean removeSuccessful = true;
Iterator<String> userGroups = user.getParentGroups(false);
while (userGroups.hasNext()) {
try {
UMHelper.removeUserFromGroup(user.getUniqueID(), userGroups.next());
} catch (UMException e) {
removeSuccessful = false;
}
}
if (!removeSuccessful) {
throw new UMException("Not all user groups could be removed");
}
}
private void addMultiple(List<Assignment> assignments) throws UMException {
boolean additionSuccessful = true;
for (Assignment assignment : assignments) {
try {
add(assignment);
} catch (UMException e) {
additionSuccessful = false;
}
}
if (!additionSuccessful) {
throw new UMException("Addition of new rights failed");
}
}
public static void addUserToGroup(String userId, String groupId) throws UMException {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Trying to add user " + userId + " to group " + groupId);
groupFactory.addUserToGroup(userId, groupId);
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Success");
}
Now the code got 3 times bigger and not as clear as it was. If I just had to stop execution after first assignment failed, the code would have been easier, but that's the requirement. Do I handle exceptions wrong or is there a way to improve the code?
In this scenario I would change all these methods from throwing exceptions to
returning a boolean value which indicates if they did their job successfully or not.
If you have control over these methods and can do this change, I think that's better
suited for your scenario.
With a little code reorganization, that is, all removals/additions/etc are in a single transaction, the code can be made clearer, as in, for instance:
String failmsg = null;
// tx is some transaction object
tx.start();
try {
failmsg = "user removal failed";
tx.removeUsers();
failmsg = "group removal failed";
tx.removeGroups();
failmsg = "new additions failed";
tx.addNew();
tx.commit();
} catch (UMException e) {
tx.rollback();
log(failmsg);
} finally {
tx.close();
}

Categories

Resources