lundi 25 février 2013

Closing a connection for you. Please close them yourself

Voici un message souvent rencontré sur les projets type JEE.
Que veut dire ce mystérieux message ? Qui l'écrit ?

Tout d'abord, sachez que se message est produit par JBoss, pour être exact, ce message est écrit par le CachedConnectionManager de JBoss, qui encapsule Hibernate.
Il s'agit d'un pool de connexion aux bases de données.

Il écrit ce message, lorsqu'il supprime une connexion de son pool parce qu'elle n'est plus utilisée alors qu'elle est encore ouverte (ce qui est contradictoire donc).

Le code suivant ne pose aucun problème, car on ferme tout :
Connection aConnection = null; /* Connexion à la base de données */
Statement aStatement = null; /* La requête */
ResultSet aResultSet = null; /* résultat de la requête */

try
{
    aConnection = getConnectionDansArbreJndiJBoss() ;
    aStatement = aConnection.prepareStatement(requete) ;
    aResultSet = aStatement.executeQuery(requete);
}
catch (SQLException e)
{
  ...
}
finally
{
    aResultSet.close(); // aResultSet != null !!!!
    aStatement.close(); // aStatement != null !!!!
    aConnection.close(); // aConnection != null !!!!
}

mais enlevez la aConnection.close() et vous verrez apparaître le message !

La difficulté avec ce message est d'identifier l'élément posant problème.

lundi 11 février 2013

Connaitre les requêtes exécutées par session sous Oracle

Afin de diagnostiquer des problèmes, il peut être opportun de connaître les requêtes exécutés par une session. Voici un exemple tiré de ce site http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:497421739750 :
COLUMN STATUS format a10
SET feedback off
SET serveroutput ON
 
COLUMN username format a20
COLUMN sql_text format a55 word_wrapped
 
SET serveroutput ON size 1000000
declare
    x number;
begin
    FOR x IN
    ( SELECT username||'('||sid||','||serial#||
                ') ospid = ' ||  process ||
                ' program = ' || program username,
             to_char(LOGON_TIME,' Day HH24:MI') logon_time,
             to_char(sysdate,' Day HH24:MI') current_time,
             sql_address, LAST_CALL_ET
        FROM v$session
       WHERE STATUS = 'ACTIVE'
         AND rawtohex(sql_address) <> '00'
         AND username IS NOT NULL ORDER BY last_call_et )
    loop
        FOR y IN ( SELECT max(decode(piece,0,sql_text,NULL)) ||
                          max(decode(piece,1,sql_text,NULL)) ||
                          max(decode(piece,2,sql_text,NULL)) ||
                          max(decode(piece,3,sql_text,NULL))
                               sql_text
                     FROM v$sqltext_with_newlines
                    WHERE address = x.sql_address
                      AND piece < 4)
        loop
            IF ( y.sql_text NOT LIKE '%listener.get_cmd%' AND
                 y.sql_text NOT LIKE '%RAWTOHEX(SQL_ADDRESS)%')
            then
                dbms_output.put_line( '--------------------' );
                dbms_output.put_line( x.username );
                dbms_output.put_line( x.logon_time || ' ' ||
                                      x.current_time||
                                      ' last et = ' ||
                                      x.LAST_CALL_ET);
                dbms_output.put_line(
                          substr( y.sql_text, 1, 250 ) );
            end IF;
        end loop;
    end loop;
end;
/
Merci à Drazzib pour l'astuce.