2010-01-23 6 views
4

Connexions fermées toujours dans le pool de connexions - pourquoi?Récupération de la source de données Jboss après le redémarrage de la base de données

servlet-

public class Index extends HttpServlet { 

    TimeZoneService timeZoneService; 

    public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException { 
     WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); 
     timeZoneService = (TimeZoneService) ctx.getBean("timeZoneService"); 
     timeZoneService.loadAllTimeZones(); 
     System.out.println("Done"); 
    } 
} 

public interface TimeZoneService { 
    void loadAllTimeZones(); 
} 

public class TimeZoneServiceImpl implements TimeZoneService { 

    private TimeZoneDao tzDao; 
    private Map<Long, String> tzOid2JavaName = new HashMap<Long, String>(); 

    public void loadAllTimeZones() { 
     List<TimeZone> timeZones = tzDao.findAllTimeZones(); 
     for (TimeZone tz : timeZones) { 
      tzOid2JavaName.put(tz.getOid(), tz.getJavaName()); 
     } 
    } 

    public void setTzDao(TimeZoneDao tzDao) { 
     this.tzDao = tzDao; 
    } 
} 

public interface TimeZoneDao { 
    List<TimeZone> findAllTimeZones() throws DataAccessException; 
} 

public class TimeZoneDaoImpl extends JdbcDaoSupport implements TimeZoneDao { 

    public List<TimeZone> findAllTimeZones() throws DataAccessException 
    { 
     StringBuffer sql = new StringBuffer(); 
     sql.append("SELECT TZ.OID, TZ.JAVA_NAME FROM TIME_ZONE TZ"); 
     List<TimeZone> timeZones = getJdbcTemplate().query(sql.toString(), new RowMapper() { 
      public Object mapRow(ResultSet rs, int i) throws SQLException { 
       TimeZone tz = new TimeZone(); 
       tz.setOid(rs.getLong("OID")); 
       tz.setJavaName(rs.getString("JAVA_NAME")); 
       return tz; 
      } 
     }); 

     return timeZones; 
    } 
} 

public class TimeZone { 
    private Long oid; 
    private String javaName; 

    public Long getOid() { 
     return this.oid; 
    } 

    public void setOid(Long oid) { 
     this.oid = oid; 
    } 

    public String getJavaName() { 
     return this.javaName; 
    } 

    public void setJavaName(String javaName) { 
     this.javaName = javaName; 
    } 
} 

ressort-config.xml

<beans> 

    <jee:jndi-lookup id="dataSource" jndi-name="java:/OracleDS"/> 

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
     <property name="dataSource" ref="dataSource"/> 
    </bean> 

    <bean id="timeZoneDao" class="dao.impl.TimeZoneDaoImpl"> 
     <property name="dataSource" ref="dataSource"/> 
    </bean> 

    <bean id="timeZoneService" class="logic.impl.TimeZoneServiceImpl"> 
     <property name="tzDao" ref="timeZoneDao"/> 
    </bean> 

</beans> 

web.xml

<web-app> 

    <display-name>Spring</display-name> 

    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value> 
      WEB-INF/spring-config.xml,classpath*:/META-INF/spring-config.xml</param-value> 
    </context-param> 

    <listener> 
     <listener-class> 
      org.springframework.web.context.ContextLoaderListener 
     </listener-class> 
    </listener> 

    <servlet> 
     <servlet-name>index</servlet-name> 
     <display-name>Index page</display-name> 
     <description>Landing page</description> 
     <servlet-class>servlet.Index</servlet-class> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>index</servlet-name> 
     <url-pattern>/index</url-pattern> 
    </servlet-mapping> 

    <!-- Session Timeout (in minutes) --> 
    <session-config> 
     <session-timeout>60</session-timeout> 
    </session-config> 
</web-app> 

mysql-ds.xml

<datasources> 
    <local-tx-datasource> 
     <jndi-name>OracleDS</jndi-name> 
     <connection-url>jdbc:mysql://localhost:3306/spring</connection-url> 
     <driver-class>com.mysql.jdbc.Driver</driver-class> 
     <user-name>spring_test</user-name> 
     <password>spring_test13</password> 
     <min-pool-size>1</min-pool-size> 
     <max-pool-size>5</max-pool-size> 
     <idle-timeout-minutes>2</idle-timeout-minutes> 
    </local-tx-datasource> 
</datasources> 
+0

mysql-ds.xml <-tx-datasource locale> OracleDS jdbc: mysql: // localhost: 3306/printemps com.mysql.jdbc.Driver spring_test spring_test13 1 <-piscine de taille max> 5 2 Prasanth

Répondre

2

Il s'agit d'un problème courant lié à l'utilisation d'un pool de connexions. Lorsque l'application emprunte une connexion au pool, est-ce que le pool doit lui-même "tester" la connexion pour s'assurer qu'elle est toujours valide, ou doit-elle laisser cela à l'application?

Si le pool teste la connexion, cela implique inévitablement l'envoi d'un élément de la connexion au serveur de base de données (généralement un SELECT de base quelconque). Sur les systèmes à trafic élevé, cela représente un gaspillage énorme et peut ajouter un stress considérable au serveur de base de données. Toutefois, sur les sites à faible trafic, où votre base de données peut gérer la charge supplémentaire, vous pouvez configurer votre source de données pour que JBoss valide la connexion avant de la transmettre à votre application. Si la connexion est morte, JBoss l'enlèvera du pool et en obtiendra un nouveau, ce qui survivra au redémarrage de la base de données.

Tout, ajoutez à votre fichier mysql-ds.xml:

<check-valid-connection-sql>select 1 from mytable</check-valid-connection-sql> 

Vous devez choisir la requête vous, assurez-vous qu'il est pas un cher, parce que ça va être exécuté un beaucoup. Voir le JBoss documentation wiki pour voir comment modifier ces fichiers de sources de données.

+0

Oui. il y a cela et une configuration de plus pour voir que Jboss fait quelque chose avant qu'il ne renvoie une connexion. valid-connection-checker-class-name est supposé être 'meilleur' ​​que l'émission d'un SQL. Puisque vous avez mentionné que cette application devrait être capable de gérer la situation, je me demandais si les frameworks Hibernate/Spring le faisaient pour nous? Depuis les exceptions de connexion fermée viennent avec des codes standard pour toutes les bases de données. – Prasanth

+0

Non, ni Spring ni Hibernate ne peuvent mieux s'en sortir. Si vous devez redémarrer votre serveur de base de données, utilisez le vérificateur de connexion ou redémarrez votre serveur d'applications. Oh, et 'valid-connection-checker-class-name' publie également SQL, il le fait juste sous les couvertures. Ça ne fait aucune différence. – skaffman

+0

@skaffman À l'exception du org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker qui utilise un ping tns, comme vous mentionner ici http://stackoverflow.com/a/145889/274414 –

7

Ok. Espérons ce qui suit est utile pour quelqu'un :-)

Il y a un paramètre de configuration de source de données - exception-sorter-class-name

Selon Jboss ceci est utilisé pour a class that looks at vendor specific messages to determine whether sql errors are fatal and thus the connection should be destroyed. If none specified, no errors will be treated as fatal.

Si en utilisant la base de données Oracle cette configuration est définie sur org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter . Cette classe a tous les codes d'erreur qui doivent être traités comme fatals et donc la connexion doit être détruite.

Dans Jboss 4, les codes d'erreur 17002 (réinitialisation de la connexion) & & 17008 (connexion fermée) ne sont pas inclus. Ils sont ajoutés dans Jboss 5. Donc, si vous utilisez Jboss 4 et que vous vous demandez pourquoi les connexions ne sont pas récupérées, essayez d'ajouter les codes manquants.

1

configuration validaton de connexion est ici avec oracle DB pour jboss 7.1+:

<validation> 
    <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.vendor.OracleValidConnectionChecker"/> 
    <check-valid-connection-sql>select 1 from dual</check-valid-connection-sql> 
    <stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.vendor.OracleStaleConnectionChecker"/> 
    <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter"/> 
</validation> 

Maintenant, Jboss validera chaque connexion.

Questions connexes