DSRA9110E: Statement is closed occurs inside a Thread's run() in Websphere

1.6k Views Asked by At

I am creating a thread in a web application in the following way. Creating a thread in web application is perhaps not the right thing to do but unfortunately that is how it has been done in my application.

The thread has to call a stored procedure making use of the same connection object passed to its runnable object. But the procedure doesn't get executed because of an error DSRA9110E: Statement is closed. Intermittently I also get "Connection is closed." Note that this happens only in IBM Websphere and there are no issues when deployed in Apache Tomcat.

Is it possible that the thread gets running i.e. thread.start() is executed before persistReconcileRecord method gets completed.

I am unable to understand what causes this statement/connection is closed issue. I appreciate any help regarding this issue. Please tell me if more information is required.

public class MyServiceImpl{
    private ReconDAO reconDAO = new ReconDAO();

    public String anyMethod(String infodom,ReconModel recon){

       //persistReconcileRecord is a method in DAO class.
        reconDAO.persistReconcileRecord(infodom, recon,"I");
        Connection connection=DBManager.getConnection(infodom);
        WorkerThread worker=new WorkerThread(infodom,recon.getReconciliationId(),"I",connection);
        Thread thread=new Thread(worker);
        thread.start();

        JSONObject jsonObj=new JSONObject();
        jsonObj.put("EXIST_VALIDATION", "false");
        jsonObj.put("RECONCILIATION_ID", recon.getReconciliationId());
                return jsonObj.toString();

            }

        }

    public class ReconDAO{
      public void persistReconcileRecord(String infodom,ReconModel reconModel) throws Exception{
       try{
        //This method creates a new connection and inserts records into database and then closes it.
      }catch(Exception e){

    }finally{
       closeConnection(connection);
       closePreparedStatement(pstmt);
    }

    }

public class WorkerThread implements Runnable{

    private String infodom;
    private Long reconciliationId;
    private String operation;
    private Connection connection;
    //A parameterized constructor to initialize all instance variables

    public void run(){
       //Uses the connection object from this class and then closes it in finally block
      //Calls a stored procedure
    }



}
1

There are 1 best solutions below

2
On

There are a couple of problems with what your application is attempting. First, the JDBC programming model does not support multi-threaded access to connections. Second, even if it did support this, the manner in which the application passes the connection handle to another thread and then proceeds to close the connection means that the when the thread runs, the connection is closed from underneath it. Per JDBC spec, close of a connection requires its statements to be closed. So the behavior you are seeing is by design (and you could expect to see even worse unpredictable errors like IllegalStateException/ArrayIndexOutOfBoundsException and so forth if it hits the former pattern rather than the latter)

Note that JDBC does support multi-threaded access to data sources. So the proper pattern for the application to use would be to supply the data source to the thread, and the thread can obtain its own connection and close it when finished. You should also consider a more proper approach to threading in Java EE applications. Depending on which version of WebSphere Application Server you are using, that could be Java EE Concurrency (spec standard as of Java EE 7) or Asynchronous Beans.