I am bit curious to know in the below code snippet, is there any chances of database connection not being closed. I am getting an issue in the SonarQube telling "Method may fail to close database resource"
try {
con = OracleUtil.getConnection();
pstmtInsert = con.prepareStatement(insertUpdateQuery);
pstmtInsert.setString(++k, categoryCode);
pstmtInsert.clearParameters();
pstmtInsert = con.prepareStatement(updateQuery);
for (i = 0; i < userList.size(); i++) {
pstmtInsert.setString(1, p_setId);
addCount = pstmtInsert.executeUpdate();
if (addCount == 1) {
con.commit();
usercount++;
} else {
con.rollback();
}
}
}
catch (SQLException sqle) {
_log.error(methodName, "SQLException " + sqle.getMessage());
sqle.printStackTrace();
EventHandler.handle();//calling event handler
throw new BTSLBaseException(this, "addInterfaceDetails", "error.general.sql.processing");
}
catch (Exception e) {
_log.error(methodName, " Exception " + e.getMessage());
e.printStackTrace();
EventHandler.handle();//calling event handler
throw new BTSLBaseException(this, "addInterfaceDetails", "error.general.processing");
}
finally {
try {
if (pstmtInsert != null) {
pstmtInsert.close();
}
} catch (Exception e) {
_log.errorTrace(methodName, e);
}
try {
if (con != null) {
con.close();
}
} catch (Exception e) {
_log.errorTrace(methodName, e);
}
if (_log.isDebugEnabled()) {
_log.debug("addRewardDetails", " Exiting addCount " + addCount);
}
}
Thanks in advance
If you are using Java 7+, I suggest you use try-with-resources. It ensures the resources are closed after the operation is completed.
Issue has been resolved when I closed the first prepare statement before starting the another one.
added below code snippet after the line pstmtInsert.clearParameters();
try {
if (pstmtInsert != null) {
pstmtInsert.close();
}
} catch (Exception e) {
_log.errorTrace(methodName, e);
}
Related
I’m using Javassist (3.25.0-GA) and Java 8 with a custom Agent to transform bytecode and add print statements to existing catch{} clauses. This works for simple cases, but has a problem with the compiled bytecode of the try-with-resources syntax.
Here is a basic example of what I'm trying to do and the results when it works correctly on standard try/catch blocks:
// before byte code manipulation
public void methodWithCatchClause() {
try {
throwsAnException();
} catch (Exception ex) {
handleException(ex);
}
}
// after byte code manipulation
public void methodWithCatchClause() {
try {
throwsAnException();
} catch (Exception ex) {
System.out.println("CATCH CLAUSE!"); // added by Javassist
handleException(ex);
}
}
The logic I'm using to transform the bytecode is inspired by another SO post [0]:
// from https://stackoverflow.com/questions/51738034/javassist-insert-a-method-at-the-beginning-of-catch-block
ControlFlow cf = new ControlFlow(ctMethod); // ctMethod == methodWithCatchClause()
for (ControlFlow.Block block : cf.basicBlocks()) {
ControlFlow.Catcher catchers[] = block.catchers();
for (int i = 0; i < catchers.length; i++) {
ControlFlow.Catcher catcher = catchers[i];
ControlFlow.Block catcherBlock = catcher.block();
int position = catcherBlock.position();
int lineNumber = ctMethod.getMethodInfo().getLineNumber(position);
ctMethod.insertAt(lineNumber + 1, "System.out.println(\"CATCH CLAUSE!\");");
}
}
But this code breaks in conjunction with the try-with-resources syntax. As a concrete example this code:
public void tryWithResources() {
try (TestAutoClosable test = new TestAutoClosable()) {
test.doStuff();
} catch (Exception ex) {
handleException(ex);
}
}
Turns into this after code generation:
public void tryWithResources() {
try {
TestAutoClosable test = new TestAutoClosable();
Throwable var2 = null;
try {
System.out.println("CATCH CLAUSE!");
test.doStuff();
} catch (Throwable var12) {
var2 = var12;
throw var12;
} finally {
if (test != null) {
if (var2 != null) {
try {
test.close();
} catch (Throwable var11) {
var2.addSuppressed(var11);
}
} else {
test.close();
}
}
}
} catch (Exception var14) {
System.out.println("CATCH CLAUSE!");
System.out.println("CATCH CLAUSE!");
System.out.println("CATCH CLAUSE!");
// this goes on for 15 more entries...
this.handleException(var14);
}
}
This of course is causing "CATCH CLAUSE!" to be printed multiple times in odd places. It might be helpful to mention that empty catch clauses, regardless of try/catch syntax, break in a similar fashion (maybe the underlying cause is related?).
I would expect something closer to this as the end result:
public void tryWithResources() {
try {
TestAutoClosable test = new TestAutoClosable();
Throwable var2 = null;
try {
test.noop();
} catch (Throwable var12) {
System.out.println("CATCH CLAUSE!");
var2 = var12;
throw var12;
} finally {
if (test != null) {
if (var2 != null) {
try {
test.close();
} catch (Throwable var11) {
var2.addSuppressed(var11);
}
} else {
test.close();
}
}
}
} catch (Exception var14) {
this.handleException(var14);
}
}
I'm trying to figure out if I have a simple error in my code or if my approach is entirely wrong. I would appreciate any help with the matter. Thanks in advance.
[0] Javassist: insert a method at the beginning of catch block
To my understanding it is possible with this code that when changing a user role another user can change the same role and always wins the last. It would even be possible for us to store parts of one and parts of the other. This is possible due to the 3 queries in the DAO. I would like to get "ThreadSafe" that during a change not another user can make a change or it will be detected that someone changed it before.
My idea was to change the method in the RoleManager.
Idea:
public interface RoleManager {
static synchronized void EditRole(UserRoleBO editedObjet, UserRoleBO nonEditedObject);
This does not work with this type of design(with a interface).
My Question:
Is there an elegant way to solve the problem without changing the
design?
Addition Note:
Tell me if i have big mistakes in my code.
Manager:
public class RoleManagerImpl implements RoleManager {
#Override
public void editRole(UserRoleBO editedObjet, UserRoleBO nonEditedObject) {
EditUserRole editUserRole = EditUserRole.Factory.createEditUserRole(nonEditedObject);
boolean hasChangedBeforeInDB = editUserRole.detectChanges();
if (hasChangedBeforeInDB) {
throw new ManagerException(ManagerException.TYPE.HASCHANGEDBEFOREINDB, null);
}
RoleDAO roleDAO = new RoleDAOImpl();
roleDAO.editRole(editedObjet);
}
}
DAO:
#Override
public int editRole(UserRoleBO role) {
Connection conn = null;
int status;
try {
//Set up connection
conn = ConnectionPool.getInstance().acquire();
DSLContext create = DSL.using(conn, SQLDialect.MARIADB);
//sql processing and return
status = create.executeUpdate(role.getRole());
EditUserRole editUserRole = EditUserRole.Factory.createEditUserRole(role);
editUserRole.detectChanges();
addPermission(editUserRole.getAddlist(), role.getRole());
deletePermissions(editUserRole.getDeleteList(), role.getRole());
}
// Error handling sql
catch (MappingException e) {
throw new DAOException(DAOException.TYPE.MAPPINGEXCEPTION, e);
}
catch (DataAccessException e) {
throw new DAOException(DAOException.TYPE.DATAACCESSEXECPTION, e);
}
catch (Exception e) {
throw new DAOException(DAOException.TYPE.UNKOWNEXCEPTION, e);
} finally {
//Connection release handling
try{
if(conn != null) {
ConnectionPool.getInstance().release(conn);
}
}
// Error handling connection
catch (DataAccessException e) {
throw new DAOException(DAOException.TYPE.RELEASECONNECTIONEXCEPTION, e);
}
catch (Exception e) {
throw new DAOException(DAOException.TYPE.UNKOWNRELEASECONNECTIONEXCEPTION, e);
}
}
//Return result
return status;
}
Thanks for helping.
this is just a possible answer. In my case, i use jooq and a mariadb.
With the assumption that we only have one central database this solution works. In a cluster, there is always the problem of the split brain.
What happens is that I lock the rows. So if the next thread tries to lock this he must wait. If it is allowed to continue, the exception HASCHANGEDBEFOREINDB is thrown.
Take care u have to commit or rollback to end the lock.
EditRole:
#Override
public int editRole(UserRoleBO editedRole ,UserRoleBO nonEditedRole) throws SQLException {
Connection conn = null;
int status;
try {
//Set up connection
conn = ConnectionPool.getInstance().acquire();
conn.setAutoCommit(false);
DSLContext create = DSL.using(conn, SQLDialect.MARIADB);
//lock rows
lockRowsOf(editedRole, conn);
EditUserRole editUserRole = EditUserRole.Factory.createEditUserRole(nonEditedRole);
boolean hasChangedBeforeInDB = editUserRole.detectChanges();
if (hasChangedBeforeInDB) {
throw new DAOException(DAOException.TYPE.HASCHANGEDBEFOREINDB, null);
}
EditUserRole editUserRole2 = EditUserRole.Factory.createEditUserRole(editedRole);
editUserRole2.detectChanges();
//sql processing and return
status = create.executeUpdate(editedRole.getRole());
addPermission(editUserRole2.getAddlist(), editedRole.getRole().getId(), conn);
deletePermissions(editUserRole2.getDeleteList(), editedRole.getRole(), conn);
conn.commit();
}
// Error handling sql
catch (MappingException e) {
conn.rollback();
throw new DAOException(DAOException.TYPE.MAPPINGEXCEPTION, e);
}
catch (DataAccessException e) {
conn.rollback();
throw new DAOException(DAOException.TYPE.DATAACCESSEXECPTION, e);
}
catch (Exception e) {
conn.rollback();
throw new DAOException(DAOException.TYPE.UNKOWNEXCEPTION, e);
} finally {
//Connection release handling
try{
if(conn != null) {
conn.setAutoCommit(true);
ConnectionPool.getInstance().release(conn);
}
}
// Error handling connection
catch (DataAccessException e) {
throw new DAOException(DAOException.TYPE.RELEASECONNECTIONEXCEPTION, e);
}
catch (Exception e) {
throw new DAOException(DAOException.TYPE.UNKOWNRELEASECONNECTIONEXCEPTION, e);
}
}
//Return result
return status;
}
Lock:
#Override
public void lockRowsOf(UserRoleBO role, Connection conn) {
int status;
try {
DSLContext create = DSL.using(conn, SQLDialect.MARIADB);
//sql processing and return
status = create.select()
.from(AUTH_ROLE)
.where(AUTH_ROLE.ID.eq(role.getRole().getId()))
.forUpdate().execute();
status = create.select()
.from(AUTH_ROLE_PERMISSION)
.where(AUTH_ROLE_PERMISSION.ROLE_ID.eq(role.getRole().getId()))
.forUpdate().execute();
}
// Error handling sql
catch (MappingException e) {
throw new DAOException(DAOException.TYPE.MAPPINGEXCEPTION, e);
}
catch (DataAccessException e) {
throw new DAOException(DAOException.TYPE.DATAACCESSEXECPTION, e);
}
catch (Exception e) {
throw new DAOException(DAOException.TYPE.UNKOWNEXCEPTION, e);
} finally {
//Connection will still needed to buffer the delete and insert
}
}
Can anyone help me out how to catch both IOException and IIOException, because i need to differentiate image format and image load error.
Something like this is not working because i am not catching IOException.
catch (IIOException e)
{
System.out.println("Invalid image format: " + e.getMessage());
Throwable t = e.getCause();
if ((t != null) && (t instanceof IOException)) {
System.out.println("Unable to load image: " + e.getMessage());
}
}
Thats why we have separate catch statements:
try {
}
catch (ExceptionTypeA e1) { }
catch (ExceptionTypeB e2) { }
try {
bim=ImageIO.read(new File(....));
int[] a={2, 2, 3,4 };
a[7]=4;
}
catch (ArrayIndexOutOfBoundsException ex2) { System.err.println("error 2 "+ex2); }
catch (Exception ex) { System.err.println("error 1 "+ex); }
Exceptions need to be given in order of specificity; i.e. in your case,
catch (IIOException ex) { System.err.println("error 1 "+ex); }
catch (IOException ex2) { System.err.println("error 2 "+ex2); }
Have you tried something like this
catch(IOException e)
{
if(e instanceof IIOException)
{
System.out.println("Invalid image format: " + e.getMessage());
}else
{
System.out.println("Unable to load image: " + e.getMessage());
}
}
I am using Jackcess API in my Eclipse plugin project. I added jackcess-2.1.0.jar file under resources/lib. I included the jar under my Binary build and in build.properties. I successfully make a connection using connection string but my DatabaseBuilder.open() call is not executing. My code is
public void run() {
try {
File tempTarget = File.createTempFile("eap-mirror", "eap");
try {
this.source = DriverManager.getConnection(EaDbStringParser.eaDbStringToJdbc(sourceString));
this.source.setReadOnly(true);
try {
FileUtils.copyFile(new File(templateFileString), tempTarget);
} catch (IOException e) {
e.printStackTrace();
}
// Changes
try {
this.target = DatabaseBuilder.open(tempTarget);
} catch (IOException e) {
e.printStackTrace();
}
Collection<String> tables = selectTables(source);
long time = System.currentTimeMillis();
for (String tableName : tables) {
long tTime = System.currentTimeMillis();
Table table = target.getTable(tableName);
System.out.print("Mirroring table " + tableName + "...");
table.setOverrideAutonumber(true);
copyTable(table, source, target);
System.out.println(" took "+ (System.currentTimeMillis() - tTime));
}
System.out.println("Done. Overall time: "+ (System.currentTimeMillis() - time));
System.out.println("done");
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// More Code here
} catch (IOException e1) {
}
}
When I run the class in debug mode and I reach DatabaseBuilder.open call it fails.
Here is my project structure:
Can anyone tell me the possible reason for it ?
The .open method of DatabaseBuilder expects to open an existing well-formed Access database file. The .createTempFile method of java.io.File creates a 0-byte file. So, the code
File dbFile;
try {
dbFile = File.createTempFile("eap-mirror", "eap");
try (Database db = DatabaseBuilder.open(dbFile)) {
System.out.println(db.getFileFormat());
} catch (IOException ioe) {
ioe.printStackTrace(System.out);
}
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
System.out.println("Finally...");
}
will cause Jackcess to throw
java.io.IOException: Empty database file
when it tries to do DatabaseBuilder.open(dbFile).
Instead, you should DatabaseBuilder.create to convert the 0-byte file into a real Access database file like this
File dbFile;
try {
dbFile = File.createTempFile("eap-mirror", ".accdb");
dbFile.deleteOnExit();
try (Database db = DatabaseBuilder.create(Database.FileFormat.V2010, dbFile)) {
System.out.println(db.getFileFormat());
} catch (IOException ioe) {
ioe.printStackTrace(System.out);
}
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
System.out.println("Finally...");
}
I am getting an error in my java servlet. The servlet fills the fields of an existing pdf. The page pulls up an alert asking "Do you want to open or save this file?" So if I press "Open" or "Save" it works fine, and does the correct thing. But.... if I press "Cancel", nothing pops up, and I get this error:
com.evermind.server.http.HttpIOException: An existing connection was forcibly closed by the remote host
I am not sure why or where this error is coming about, but it says that the error is happening on this line:
stamp.close();
If more code snippets are needed, please let me know. I just didnt want to paste everything in here, because I dont exactly know where it is happening. Thanks in advance.
EDIT
Here is the majority of my relevant code:
try {
conn = ((DataSource) new InitialContext().lookup(dSource)).getConnection();
stmt = conn.prepareStatement("....");
rs = stmt.executeQuery();
if (rs.next()) {
....
}
stmt = conn.prepareStatement("....");
rs = stmt.executeQuery();
if (rs.next()) {
....
}
if (isTempVerification) {
final String tempFile = "TemporaryVerification.pdf";
try {
response.setHeader(contentDisposition, "attachment; filename=" + tempFile);
reader = new PdfReader(this.getServletContext().getResource("/pdf/" + tempFile));
stamp = new PdfStamper(reader, response.getOutputStream());
form = stamp.getAcroFields();
form.setField("date", current);
form.setField("reply_line", replyLine);
form.setField("first_middle_last", fmlName);
form.setField("term_year_1", termYear + ".");
form.setField("census_date", termCensus);
form.setField("term_year_2", termYear + ".");
//stamp.setFormFlattening(true);
stamp.close();
} catch (IOException e) {
errorFound = true;
e.printStackTrace(System.err);
} catch (DocumentException e) {
errorFound = true;
e.printStackTrace(System.err);
}
} else {
final String officialFile = "OfficialVerification.pdf";
try {
response.setHeader(contentDisposition, "attachment; filename=" + officialFile);
reader = new PdfReader(this.getServletContext().getResource("/pdf/" + officialFile));
stamp = new PdfStamper(reader, response.getOutputStream());
form = stamp.getAcroFields();
form.setField("date", current);
form.setField("reply_line", replyLine);
form.setField("first_middle_last", fmlName);
form.setField("status", studentStatus);
form.setField("hr", hoursTaken);
form.setField("term_year", termYear);
form.setField("start_end_date", termStart + " - " + termEnd);
//stamp.setFormFlattening(true);
stamp.close();
} catch (IOException e) {
errorFound = true;
e.printStackTrace(System.err);
} catch (DocumentException e) {
errorFound = true;
e.printStackTrace(System.err);
}
}
} catch (NamingException e) {
e.printStackTrace(System.err);
} catch (SQLException e){
e.printStackTrace(System.err);
} finally {if (stmt != null) try {stmt.close();
} catch (SQLException e){
e.printStackTrace(System.err);
} if (rs != null) try {rs.close();
} catch (SQLException e){
e.printStackTrace(System.err);}
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace(System.err);
}
}
when u make the stamp.close() call, the output stream is also flushed. since you set the response headers before stamp.close(), the response headers are also written to the client. consequently, this causes the file download dialog to appear on the client. when the client clicks 'cancel', the http connection is terminated.
your servlets need to maintain the http connection throughout its execution as it will be writing output to the response output stream. if the http connection is terminated before the response has been committed, you will get the exception that you are seeing now.