J'ai besoin d'exécuter plusieurs instructions d'initialisation sur chaque connexion empruntée à partir d'un pool JDBC Tomcat. Je ne peux pas utiliser JDBCInterceptors car le pool est partagé avec d'autres applications qui n'auront pas besoin de cette initilisation. J'utilise Spring Boot 1.4.4, déployant sur Tomcat 8.5.11, qui a un ResourceLink dans context.xml à une ressource dans server.xml qui définit le DataSource par rapport à une base de données Oracle 11g. J'accède à DataSource via JNDI.L'aspect échoue avec ClassCastException essayant de pointer Tomcat DataSource getConnection
En réponse à cette question https://stackoverflow.com/a/38746398 Je voulais utiliser Spring AOP pour atteindre mon objectif.
J'ai créé et aspect qui fonctionne parfaitement si le DataSource est défini directement dans context.xml, mais échoue avec un ClassCastException si référencé par un ResourceLink à la même définition dans server.xml
L'exception est la suivante:
java.lang.ClassCastException: org.apache.tomcat.jdbc.pool.DataSource cannot be cast to org.apache.tomcat.jdbc.pool.DataSourceProxy
at org.apache.tomcat.jdbc.pool.DataSourceProxy$$FastClassBySpringCGLIB$$26808f96.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
at org.apache.tomcat.jdbc.pool.DataSource$$EnhancerBySpringCGLIB$$17f85659.getConnection(<generated>)
Ma classe d'image:
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DataSourceAspect {
private static final Logger LOG = LoggerFactory.getLogger(DataSourceAspect.class);
@AfterReturning(pointcut = "execution(* org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection())")
public void afterConnectionEstablished() {
LOG.info("Borrowed connection from the pool. Initializing...");
}
}
définition ResourceLink dans context.xml:
<ResourceLink name="jdbc/us_j2eeCoreDS"
global="jdbc/us_j2eeCoreDS"
type="javax.sql.DataSource"/>
définition DataSource dans server.xml (changé de valeurs privées):
<Resource name="jdbc/us_j2eeCoreDS" type="javax.sql.DataSource"
global="jdbc/us_j2eeCoreDS"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="oracle.jdbc.OracleDriver"
username="xxx" password="xxx"
initialSize="1"
minIdle="1"
maxIdle="4" maxWaitMillis="5000"
maxActive="40"
removeAbandonedOnBorrow="true" removeAbandonedTimeout="300"
testWhileIdle="true"
validationQuery="SELECT 1 FROM DUAL"
timeBetweenEvictionRunsMillis="60000"
url="jdbc:oracle:thin:@host:port:SID"/>
Comme je l'ai dit, si je définis la même DataSource exacte à context.xml, cela fonctionne parfaitement.
Une idée?
Merci beaucoup.