Executed rollbackon connection - mysql

i am using JDBC to connect my MySQL database. I am trying to delete data from 2 tables (tasks and tasks_users(join table)). Look at my code:
#Override
public int deleteById(Long id) throws SQLException {
deleteByIdFromJoinTable(id);
int updated_rows;
sessionManager.beginSession();
try(Connection connection = sessionManager.getCurrentSession();
PreparedStatement statement = connection.prepareStatement(SQL_QUERIES.DELETE_TASK_BY_ID.QUERY)) {
statement.setLong(1, id);
updated_rows = statement.executeUpdate();
sessionManager.commitSession();
}catch (SQLException exception){
log.error(exception.getMessage(), exception);
sessionManager.rollbackSession();
throw exception;
}
return updated_rows;
}
public void deleteByIdFromJoinTable(Long id) throws SQLException {
sessionManager.beginSession();
try(Connection connection = sessionManager.getCurrentSession();
PreparedStatement statement = connection.prepareStatement(SQL_QUERIES.DELETE_TASK_FROM_TASKS_USERS.QUERY)) {
statement.setLong(1, id);
statement.executeUpdate();
sessionManager.commitSession();
}catch (SQLException exception){
log.error(exception.getMessage(), exception);
sessionManager.rollbackSession();
throw exception;
}
}
enum SQL_QUERIES {
DELETE_TASK_BY_ID("DELETE FROM tasks WHERE id=(?)"),
DELETE_TASK_FROM_TASKS_USERS("DELETE FROM tasks_users WHERE task_id=(?)");
final String QUERY;
SQL_QUERIES(String QUERY) {
this.QUERY = QUERY;
}
}
}
But when i call deleteById(), i get exception like:
13:58:03.079 [http-nio-8080-exec-9] DEBUG com.zaxxer.hikari.pool.ProxyConnection - restServiceDbPool - Executed rollback on connection com.mysql.cj.jdbc.ConnectionImpl#68421fee due to dirty commit state on close()
Connection to database works well, method, where i get all tasks returns them without problems.
What's problem is here, i will be very grateful for help?

Related

Junit test cases for delete operation with try and catch block - handling Exception

public UserNoteDefination deleteByNoteCd (UserNoteDefination request, LogDTO log) {
log.setComponent("ClientRequestService.deleteByNoteCd");
UserNoteDefination response new UserNoteDefination();
String tabllame = request.getTabName();
String noteCd-request.getNoteCd();
if (tabName.equalsIgnoreCase("UND_TABLE"))
{
try
userNoteDefRepository.deleteById(noteCd);
response.setMsg("Completed");
log.setPayload("[FROM:UI] clientRequest:Delete Successfully");
loggingService.log(GuiServiceConstants.INFO LEVEL, log);
}
catch (Exception e){
response.setMsg("Error");
log.setPayload("[FROM:UI] clientRequest:Error occured while delete");
loggingService.log(GuiServiceConstants.ERROR LEVEL, log);
}
return response;
}
This is my junit code in mockito
#Test public void deleteByNoteCd() throws Exception {
LogDTO log = new LogDTO(); log.setComponent("ClientRequestService.getClientRequest");
UserNoteDefination response = new UserNoteDefination();
response.setNoteCd("TEST7");
response.setMsg("Completed");
response.setTabName("UND TABLE");
UserNoteDefination rval - service.deleteByNoteCd(response, log);
assertNotNull(rval);
}
I'm unable to cover the exception part. Cab someone help

mocking database connection by using mockito

public List<Prisma> getProductCharacteristics(ResultSetLoadHandler<Prisma> rsLoadHandler, SqlSession sqlSession) throws Exception {
List<Prisma> ptos = null;
try {
sqlSession.select("Product.getProductInformation", params, rsLoadHandler);
ptos = rsLoadHandler.getResults();
} catch (Exception e) {
throw e;
}
return ptos;
}
I am trying to mock the select method
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return rsLoadHandler;
}
}).when(sqlSession).select(rsLoadHandler, sqlSession);
but not able to mock sqlSession.select(String statement, Object parameter, ResultHandler handler); in mockito framework.
Getting this issue:
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not
get JDBC Connection; nested exception is
org.apache.commons.dbcp.SQLNestedException: Cannot create
PoolableConnectionFactory (ORA-28000: the account is locked )
I am using ibatis database, I need to mock the db calls
I should not hit the database and return the list size to be greater than zero.

MySQL connection pooling with JERSEY

I'm developping a RESTful API with Jersey and MySQL.
I'm actually using the JDBC driver to connect to the database and I create a new connection everytime I want to acess it. As it clearly is a memory leakage, I started to implement the ServletContextClassclass but I don't know how to call the method when I need to get the result of a SQL query.
Here is how I did it wrong:
DbConnection.java
public class DbConnection {
public Connection getConnection() throws Exception {
try {
String connectionURL = "jdbc:mysql://root:port/path";
Connection connection = null;
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(connectionURL, "root", "password");
return connection;
}
catch (SQLException e) {
throw e;
}
}
}
DbData.java
public ArrayList<Product> getAllProducts(Connection connection) throws Exception {
ArrayList<Product> productList = new ArrayList<Product>();
try {
PreparedStatement ps = connection.prepareStatement("SELECT id, name FROM product");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Product product = new Product();
product.setId(rs.getInt("id"));
product.setName(rs.getString("name"));
productList.add(product);
}
return productList;
} catch (Exception e) {
throw e;
}
}
Resource.java
#GET
#Path("task/{taskId}")
#Consumes(MediaType.APPLICATION_JSON)
public Response getInfos(#PathParam("taskId") int taskId) throws Exception {
try {
DbConnection database= new DbConnection();
Connection connection = database.getConnection();
Task task = new Task();
DbData dbData = new DbData();
task = dbData.getTask(connection, taskId);
return Response.status(200).entity(task).build();
} catch (Exception e) {
throw e;
}
}
Here is where I ended up trying to implement the new class:
ServletContextClass.java
public class ServletContextClass implements ServletContextListener {
public Connection getConnection() throws Exception {
try {
String connectionURL = "jdbc:mysql://root:port/path";
Connection connection = null;
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(connectionURL, "root", "password");
return connection;
} catch (SQLException e) {
throw e;
}
}
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("ServletContextListener started");
DbConnection database = new DbConnection();
try {
Connection connection = database.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
//con.close ();
}
}
But problem is, I don't know what to do next. Any help? Thanks
You need to set the Connection variable as an attribute of the ServletContext. Also, I would recommend using connection as a static class variable so you can close it in the contextDestroyed method.
You can retrieve the connection attribute in any of your servlets later on for doing your DB operations.
public class ServletContextClass implements ServletContextListener {
public static Connection connection;
public Connection getConnection(){
try {
String connectionURL = "jdbc:mysql://root:port/path";
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(connectionURL, "root", "password");
} catch (SQLException e) {
// Do something
}
}
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("ServletContextListener started");
getConnection();
arg0.getServletContext().setAttribute("connection", connection);
}
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
try{
if(connection != null){
connection.close();
}
}catch(SQLException se){
// Do something
}
}
}
Finally access your connection attribute inside your Servlet (Resource). Make sure you pass #Context ServletContext to your Response method so you can access your context attributes.
#GET
#Path("task/{taskId}")
#Consumes(MediaType.APPLICATION_JSON)
public Response getInfos(#PathParam("taskId") int taskId, #Context ServletContext context) throws Exception {
try {
Connection connection = (Connection) context.getAttribute("connection");
Task task = new Task();
DbData dbData = new DbData();
task = dbData.getTask(connection, taskId);
return Response.status(200).entity(task).build();
} catch (Exception e) {
throw e;
}
}
Now that we have solved your current issue, we need to know what can go wrong with this approach.
Firstly, you are only creating one connection object which will be used everywhere. Imagine multiple users simultaneously accessing your API, the single connection will be shared among all of them which will slow down your response time.
Secondly, your connection to DB will die after sitting idle for a while (unless you configure MySql server not to kill idle connections which is not a good idea), and when you try to access it, you will get SQLExceptions thrown all over. This can be solved inside your servlet, you can check if your connection is dead, create it again, and then update the context attribute.
The best way to go about your Mysql Connection Pool will be to use a JNDI resource. You can create a pool of connections which will be managed by your servlet container. You can configure the pool to recreate connections if they go dead after sitting idle. If you are using Tomcat as your Servlet Container, you can check this short tutorial to get started with understanding the JNDI connection pool.

Communications link failure: how to kill dead connections from pool?

I am facing following exception:
com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: ** BEGIN NESTED EXCEPTION ** java.io.EOFException.
After specifying following pool-properties for the datasource, its able to auto-reconnect on connection-time-out; but the dead connections are existing in the pool are being reused and not being killed/evicted (ie. the validation-query and eviction parameters are not working). Following is my code. Can anyone please suggest some solution how to handle this?
public class DbConnection {
static DataSource datasource = new org.apache.tomcat.jdbc.pool.DataSource();
public static Connection getConnection() {
PoolProperties p = new PoolProperties();
p.setUrl("jdbc:mysql://192.168.0.9:3306/oet_v3?autoReconnect=true");
p.setDriverClassName("com.mysql.jdbc.Driver");
p.setUsername("root");
p.setPassword("napster123");
p.setJmxEnabled(true);
p.setTestWhileIdle(true);
p.setTestOnBorrow(true);
p.setValidationQuery("SELECT 1");
p.setTestOnReturn(true);
p.setValidationInterval(20000);
p.setTimeBetweenEvictionRunsMillis(3000);
p.setMaxActive(100);
p.setInitialSize(10);
p.setMaxWait(10000);
p.setMinEvictableIdleTimeMillis(3000);
p.setMinIdle(10);
Connection con = null;
try {
Context ctx = new InitialContext();
((DataSourceProxy) datasource).setPoolProperties(p);
con = datasource.getConnection();
Statement st1 = con.createStatement();
ResultSet rs1 = st1.executeQuery("select * from User_Login limit 0,1");
if (rs1.next()) {
System.out.println("LIVE CONNECTION********con: " + con + " rs.next=" + rs1.next());
} else {
System.out.println("&&&&&rs is null so secnd conn: " + con);
DataSource datasource1 = new org.apache.tomcat.jdbc.pool.DataSource();
((DataSourceProxy) datasource1).setPoolProperties(p);
con = datasource1.getConnection();
return con;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
} finally {
return con;
}
finally {
System.out.println("before returning con: "+con);
if (con!=null) try {return con;}catch (Exception ignore) {}
return con;
}
}
}

Glassfish "Connection closed" error with a connection pool, JDBC, and SQL Server 2008

When I try to do more than one transaction in a JSF page, I get the following error:
A potential connection leak detected for connection pool MSSQL. The stack trace of the thread is provided below :
com.sun.enterprise.resource.pool.ConnectionPool.setResourceStateToBusy(ConnectionPool.java:324)
com.sun.enterprise.resource.pool.ConnectionPool.getResourceFromPool(ConnectionPool.java:758)
com.sun.enterprise.resource.pool.ConnectionPool.getUnenlistedResource(ConnectionPool.java:632)
com.sun.enterprise.resource.pool.AssocWithThreadResourcePool.getUnenlistedResource(AssocWithThreadResourcePool.java:196)
com.sun.enterprise.resource.pool.ConnectionPool.internalGetResource(ConnectionPool.java:526)
com.sun.enterprise.resource.pool.ConnectionPool.getResource(ConnectionPool.java:381)
com.sun.enterprise.resource.pool.PoolManagerImpl.getResourceFromPool(PoolManagerImpl.java:245)
com.sun.enterprise.resource.pool.PoolManagerImpl.getResource(PoolManagerImpl.java:170)
com.sun.enterprise.connectors.ConnectionManagerImpl.getResource(ConnectionManagerImpl.java:338)
com.sun.enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:301)
com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:190)
com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:165)
com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:160)
com.sun.gjc.spi.base.DataSource.getConnection(DataSource.java:113)
cl.codesin.colegios.util.persistencia.DAOManejador.abrir(DAOManejador.java:126)
Please notice the last line I pasted:
cl.codesin.colegios.util.persistencia.DAOManejador.abrir(DAOManejador.java:126)
abrir does the following:
public void abrir() throws SQLException {
try
{
if(this.con==null || this.con.isClosed())
this.con = fuenteDatos.getConnection();
}
catch(SQLException e)
{
throw e;
}
}
It works in a singleton DAO manager this way: the DAO manager has one instance of each DAO and manages a single connection that every DAO shares. When a DAO is requested, it does the following:
public DAORegion getDAOregion() throws SQLException {
try
{
if(con == null) //con is the connection the DAO manager uses
{
this.abrir();
}
}
catch(SQLException e)
{
throw e;
}
if(this.DAOregion==null)
{
this.DAOregion = new DAORegion(this.con);
}
return DAOregion;
}
When closing a connection, the manager just calls to con.close() without anything else.
By the way, I have no persistence.xml since I'm working with JDBC.
What am I doing wrong? Thank you beforehand.
EDIT: By desactivating the leak detection from the Glassfish server I could avoid the exception, however I'm still getting a "Connection closed" error. Worst is, now I don't know exactly where the error is being thrown.
EDIT 2: I changed my DAO manager again. Here's the implementation.
public class DAOManejador {
public static DAOManejador getInstancia() {
return DAOManejadorSingleton.INSTANCIA;
}
//This is just a sample, every getDAOXXX works the same.
public DAOUsuario getDAOusuario() throws SQLException {
try
{
if(con == null)
{
this.abrir();
}
}
catch(SQLException e)
{
throw e;
}
if(this.DAOusuario==null)
{
this.DAOusuario = new DAOUsuario(this.con, this.stmt, this.res);
}
return DAOusuario;
}
public void abrir() throws SQLException {
try
{
if(this.con==null || this.con.isClosed())
this.con = fuenteDatos.getConnection();
}
catch(SQLException e)
{
throw e;
}
}
public void iniciaTransaccion() throws SQLException {
try
{
con.setAutoCommit(false);
}
catch(SQLException e)
{
throw e;
}
}
public void cierraTransaccion() throws SQLException {
try
{
con.setAutoCommit(true);
}
catch(SQLException e)
{
throw e;
}
}
public void comprometer() throws SQLException {
try
{
con.commit();
}
catch(SQLException e)
{
throw e;
}
}
public void deshacer() throws SQLException {
try
{
con.rollback();
}
catch(SQLException e)
{
throw e;
}
}
public void cerrar() throws SQLException {
try
{
if(this.stmt!=null && !this.stmt.isClosed())
stmt.close();
if(this.res!=null && !this.res.isClosed())
this.res.close();
if(this.con!=null && !this.con.isClosed())
con.close();
}
catch(SQLException e)
{
throw e;
}
}
public void comprometerYTerminarTransaccion() throws SQLException {
try
{
this.comprometer();
this.cierraTransaccion();
}
catch(SQLException e)
{
throw e;
}
}
public void comprometerYCerrarConexion() throws SQLException {
try
{
this.comprometer();
this.cierraTransaccion();
this.cerrar();
}
catch(SQLException e)
{
throw e;
}
}
//Protegidos
#Override
protected void finalize() throws SQLException, Throwable
{
try
{
this.cerrar();
}
finally
{
super.finalize();
}
}
//Private
private DataSource fuenteDatos;
private Connection con = null;
private PreparedStatement stmt = null;
private ResultSet res = null;
private DAOUsuario DAOusuario = null;
private DAORegion DAOregion = null;
private DAOProvincia DAOprovincia = null;
private DAOComuna DAOcomuna = null;
private DAOColegio DAOcolegio = null;
private DAOManejador() throws Exception {
try
{
InitialContext ctx = new InitialContext();
this.fuenteDatos = (DataSource)ctx.lookup("jndi/MSSQL");
}
catch(Exception e){ throw e; }
}
private static class DAOManejadorSingleton {
public static final DAOManejador INSTANCIA;
static
{
DAOManejador dm;
try
{
dm = new DAOManejador();
}
catch(Exception e)
{ dm=null; }
INSTANCIA = dm;
}
}
}
What I did now is to provide a single access point for every DAO. When a DAO wants to use a statement or a resource, they'll all use the same one. When they need to open again one, the system does the following:
public abstract class DAOGenerico<T> {
//Protected
protected final String nombreTabla;
protected Connection con;
protected PreparedStatement stmt;
protected ResultSet res;
protected DAOGenerico(Connection con, PreparedStatement stmt, ResultSet res, String nombreTabla) {
this.nombreTabla = nombreTabla;
this.con = con;
this.stmt = stmt;
this.res = res;
}
//Prepares a query
protected final void prepararConsulta(String query) throws SQLException
{
try
{
if(this.stmt!=null && !this.stmt.isClosed())
this.stmt.close();
this.stmt = this.con.prepareStatement(query);
}
catch(SQLException e){ throw e; }
}
//Gets a ResultSet
protected final void obtenerResultados() throws SQLException {
try
{
if(this.res!=null && !this.res.isClosed())
this.res.close();
this.res = this.stmt.executeQuery();
}
catch(SQLException e){ throw e; }
}
}
And it still doesn't work.
I tried not doing anything when closing the connection. I commented the code in the cerrar method, and for some reason, it works! Even when it's a bad practice! Is it okay to keep it like that, or should I find a way to close a connection?
Disregard this, I found what's wrong. I hope someone can make good use of this in the future.
The problem
if(this.con==null || this.con.isClosed())
this.con = fuenteDatos.getConnection();
Each time I try to open a connection, I get a completely brand new connection. What's the problem with this?
public DAOUsuario getDAOusuario() throws SQLException {
try
{
if(con == null)
{
this.abrir();
}
}
catch(SQLException e)
{
throw e;
}
if(this.DAOusuario==null)
{
this.DAOusuario = new DAOUsuario(this.con, this.stmt, this.res);
}
return DAOusuario;
}
Only when I create a new instance of the DAO I assign it a new connection. What will happen in the following case then?
DAOManejador daoManager = DAOManejador.getInstancia(); //Get an instance of the DAO manager
daoManager.abrir(); //Open the connection
DAOUsuario daoUser = daoManager.getDAOusuario(); //Get a DAOUsuario, a type of DAO. It'll have the same connection as the DAOManager, and it'll be stored in the instance of the DAO manager
... //Do database stuff
daoManager.cerrar(); //Close the connection
daoManager.abrir(); //Open the connection again. Note that this will be a new instance of the conection rather than the old one
If, from here, you try to do database stuff, you'll get a Connection closed error since daoUser will still hold the old connection.
What I did
I modified the DAO manager class. It no longer has a getDAOXXX() per DAO, but rather the following:
public DAOGenerico getDAO(Tabla t) throws SQLException {
try
{
if(con == null || this.con.isClosed())
{
this.abrir();
}
}
catch(SQLException e)
{
throw e;
}
switch(t)
{
case REGION:
return new DAORegion(this.con, this.stmt, this.res);
case PROVINCIA:
return new DAOProvincia(this.con, this.stmt, this.res);
case COMUNA:
return new DAOComuna(this.con, this.stmt, this.res);
case USUARIO:
return new DAOUsuario(this.con, this.stmt, this.res);
case COLEGIO:
return new DAOColegio(this.con, this.stmt, this.res);
default:
throw new SQLException("Se intentó vincular a una tabla que no existe.");
}
}
Each time the user requests a DAO, it'll ask the manager to return the correct type of DAO. But instead of storing each instance, the manager will create new instances depending on the current connection (con is the connection, stmt is a PreparedStatement and res is a ResultSet - they will be used so they can be closed when the manager closes the connection so nothing leaks). Tabla is an enum holding the current table names in the database so it can return the correct DAO. This worked with no problems whatsoever. The rest of the class is the same, so if you want to use it, just replace the DAOUsuario method with the one above and it should work fine.