PDA

View Full Version : [JAVA] java.sql.SQLRecoverableException: Closed Connection


chicco19811
03-06-2014, 16:20
ho una web application che gira su weblogic e si collega a oracle; non l' ho fatta io (almeno nessuno mi sgrida :-)) ma ho guardato la parte di connessione e fa qualcosa del genere


public class DBUtility {
private static Connection connection = null;

public static Connection getConnection() {
if (connection != null)
return connection;

else {

try {

String driver ="oracle.jdbc.driver.OracleDriver";
String url ="jdbc:oracle:thin:@DBSCA04:1889:SCA04";
String user ="user";
String password ="password";

Class.forName(driver);

connection = DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return connection;
// }
}
}
}



public class DBCrudCountry
{
private Connection connection;

....

public DBCrudCountry()
{
connection = DBUtility.getConnection();
}

public void updateItem(Country item, int delete)
{
delete(item);
insert(item, delete);
}

private void insert(Country item, int delete)
{
...
}


private void delete(Country item)
{
PreparedStatement preparedStatement;
try
{
preparedStatement = connection.prepareStatement("update " + tableName + " set DELETED=?" + " where ID=?");
preparedStatement.setInt(1, 1);
preparedStatement.setInt(2, item.getId());
preparedStatement.executeUpdate();
}
catch (SQLException e)
{
e.printStackTrace();
}
}

}




public class DBControllerCountry extends HttpServlet
{

private DBCrudCountry crud;


public DBControllerCountry()
{
crud = new DBCrudCountry();
}



protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
if (request.getParameter("action") != null)
{

if (action.equals("list"))
{
...
}
else if ( action.equals("delete"))
{
...
try
{
if (action.equals("create"))
{
..
}
else if (action.equals("update"))
{
...
}
else if (action.equals("delete"))
{
if (request.getParameter("id") != null)
{
item = crud.getItem(Integer.parseInt(request.getParameter("id")));
crud.updateItem(item, 1);

}
}
}
catch (Exception ex)
{
String error = "{\"Result\":\"ERROR\",\"Message\":" + ex.getStackTrace().toString() + "}";
response.getWriter().print(error);
}
}
}
}


}



funziona perfettamente ma ogni giorno devo riavviare nel senso che se oggi tutto funziona, domani mattina arrivo qua e la connessione fallisce; nei log mi da questi errori

java.sql.SQLRecoverableException: IO Error: Broken pipe
...
Caused by: java.net.SocketException: Broken pipe
...
java.sql.SQLRecoverableException: Closed Connection

dal supporto capisco che

i database vengono backuppati a freddo tutte le notti. Pertanto le connessioni lasciate attive senza un sistema di auto-reconnect non risultano più attive.

posso rimediare al codice che ho postato senza stravolgere tutto?
a me non pare correttissimo ma ho bisogno di fare nella maniera più veloce possibile, almeno per ora

grazie

Daniels118
05-06-2014, 16:31
La persona che ha scritto quel codice evidentemente non ha cognizione del fatto che un application server può servire più richieste contemporaneamente, ergo dovrebbe istanziare una nuova connessione al db per ogni richiesta.

Prova a fare queste modifiche:
1) rimuovi la variabile statica "connection" dalla classe DBUtility e fai creare al metodo getConnection una nuova connessione ogni volta che viene richiamato;
2) modifica tutte le classi che estendono HttpServlet, rimuovi la proprietà crud, ed elimina la sua creazione dal costruttore, quindi inserisci dichiarazione ed inizializzazione di crud direttamente nei metodi doPost/doGet.
Non è il massimo in termini di performance, ma di sicuro ne guadagnerai in coerenza delle operazioni.

sottovento
06-06-2014, 14:22
Io modificherei in


public static Connection getConnection() {
if (connection != null && connection.isValid(1000))
return connection;


dovrebbe essere sufficiente. Se per caso ti vene la paura che le prestazioni possano risentirne, quando catturi l'eccezione che hai descritto, chiudi la connessione (e' inutile ma sicuro) - facendo attenzione a non lasciar trapelare alcuna eccezione - e poi, metti connection a null. Al ciclo successivo ritentera' la connessione.

ATTENZIONE - questo significa che registrera' nuovamente il driver. Potresti evitare di farlo ad ogni riconnessione e farlo solo all'inizio dell'applicazione.

Daniels118
06-06-2014, 22:14
Io modificherei in


public static Connection getConnection() {
if (connection != null && connection.isValid(1000))
return connection;


dovrebbe essere sufficiente. Se per caso ti vene la paura che le prestazioni possano risentirne, quando catturi l'eccezione che hai descritto, chiudi la connessione (e' inutile ma sicuro) - facendo attenzione a non lasciar trapelare alcuna eccezione - e poi, metti connection a null. Al ciclo successivo ritentera' la connessione.

ATTENZIONE - questo significa che registrera' nuovamente il driver. Potresti evitare di farlo ad ogni riconnessione e farlo solo all'inizio dell'applicazione.
Non credo sia sufficiente perché DBCrudCountry chiama getConnection solo nel costruttore, per cui impostando connection a null, essa rimane null. Bisognerebbe invece scrivere "connection = DBUtility.getConnection()" all'interno di ogni catch di quel tipo.

sottovento
07-06-2014, 06:04
Non credo sia sufficiente perché DBCrudCountry chiama getConnection solo nel costruttore, per cui impostando connection a null, essa rimane null. Bisognerebbe invece scrivere "connection = DBUtility.getConnection()" all'interno di ogni catch di quel tipo.

Beh si, hai ragione. Non avevo letto tutto il codice, dando per scontato che fosse gia' cosi'. Chiedo perdono!!! :D

Maui78
08-06-2014, 19:01
Ciao, non conosco weblogic, ma lavoro da anni su altri application server. Verifica se sul datasource, lato weblogic, esista qualcosa che "pre-testa" la connessione. Se è ok, bene, la uso, altrimenti ne apro un'altra.
Il pretest normalmente è un qualcosa che gira a cadenza di 120 secondi o giù di lì, si esegue una query sul db, stupida, tipo un select sysdate from dual, tanto per vedere se la connessione è viva.
Per quanto l'approccio via codice potrebbe essere stato errato, magari te la cavi velocemente con un flag.

Ciao