2017-08-17 2 views
1

J'ai frappé un bloqueur lors de la migration d'une ancienne application Java vers Spring Boot. Plus précisément, l'application utilise Apache CXF pour les services Web SOAP qui permettent d'obtenir des données à partir d'une base de données Oracle. La question que je vois est que dès qu'une recherche JNDI est tentée par le service Web, l'exception suivante est levée:Spring Boot avec Tomcat intégré avec la recherche Apache CXF et JNDI javax.naming.NameNotFoundException

Nom [java: comp/env/jdbc/MyDataSource] n'est pas lié à ce contexte. Impossible de trouver [java: comp]. NamingException: javax.naming.NameNotFoundException: Nom [java: comp/env/jdbc/myDataSource] n'est pas lié dans ce contexte. Impossible pour de trouver [java: comp].

Pour référence, j'ai vérifié dans un exemple de la question ici: https://github.com/pmercer/spring-boot-sample-tomcat-jndi-cxf-ws

Donc, si quelqu'un pouvait me montrer un exemple de travail et/ou offrent des conseils pour résoudre le problème, il serait alors très appréciée.

Ajout plus de détails ...

Voici comment la recherche est effectuée dans l'application existante, qui est déployé en tant que fichier .war sur un serveur Tomcat externe ...

/** 
* Returns a database connection for the specified datasource 
* @param db - ex. "jdbc/DatasourceXyz" 
* @return db Connection 
* @throws Exception 
*/ 
public static Connection getDbConnection(String db) throws Exception { 
    java.sql.Connection conn = null; 

    try { 
     LOG.debug("getting db connection for " + db + " ..."); 

     javax.naming.Context initCtx = new javax.naming.InitialContext(); 
     javax.naming.Context envCtx = (javax.naming.Context) initCtx.lookup("java:comp/env"); 
     javax.sql.DataSource ds = (javax.sql.DataSource) envCtx.lookup(db); 
     conn = ds.getConnection(); 

     initCtx.close(); 
     LOG.debug("got db connection for " + db); 
     LOG.debug("url = " + conn.getMetaData().getURL()); 

    } catch (Exception e) { 
     String message = String.format("Exception thrown while creating a JDBC connection for %s: %s", db, 
       e.getMessage()); 
     throw new Exception(message); 
    } 

    return conn; 
} 

Et la propriétés de base de données sont stockées dans le fichier context.xml de serveur Tomcat ...

<Context> 
<WatchedResource>WEB-INF/web.xml</WatchedResource> 
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> 
<!-- environment-specific jdbc data sources: --> 
<Resource name="jdbc/DatasourceXyz" auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver" url="jdbc:oracle:thin:@hostname:1521:database" username="someUser" password="***" maxTotal="20" maxIdle="10" maxWaitMillis="60000"/> 
<!-- set other jdbc data sources below: --> 

En outre, étant donné que les invocations de méthode getDbConnection existantes sont répandues et que le code CRUD de la base de données de l'application est étendu, le but est de laisser ce code tel quel. Donc, fondamentalement, j'ai juste besoin d'être en mesure de créer la connexion de base de données, comme si ...

public static Connection getDbConnection(String db) throws Exception { 
    java.sql.Connection conn = null; 

    try { 
     LOG.debug("getting db connection for " + db + " ..."); 

     // Get the SampleUtilService from the Bridge 
     SampleUtilService sampleUtilService = SpringContextBridge.services().getSampleUtilService(); 

     // Get DataSource from the JndiObjectFactoryBean 
     javax.sql.DataSource ds = sampleUtilService.getDataSourcefromFactoryBean(db); 

     conn = ds.getConnection(); 

     LOG.debug("got db connection for " + db); 
     LOG.debug("url = " + conn.getMetaData().getURL()); 

    } catch (Exception e) { 
     String message = String.format("Exception thrown while creating a JDBC connection for %s: %s", db, 
       e.getMessage()); 
     throw new Exception(message); 
    } 

    return conn; 
} 

Ainsi, avec l'aide de la fonctionnalité SpringContextBridge et la configuration JNDI via un serveur Tomcat intégré, comme crédité dans mon échantillon README du projet, fondamentalement c'est mon plan. De plus, comme je suis relativement nouveau à Spring Boot, je ne suis pas sûr que ce soit la meilleure approche ou non.

Aussi, après avoir fait quelques tests supplémentaires après mon post initial, il semble que la question que je voyais pourrait simplement être due en définissant la propriété JndiObjectFactoryBean.setLookupOnStartup false, ie.,

@Bean(destroyMethod="") 
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException { 
    JndiObjectFactoryBean bean = new JndiObjectFactoryBean(); 
    bean.setJndiName("java:comp/env/jdbc/myDataSource"); 
    bean.setProxyInterface(DataSource.class); 
    bean.setLookupOnStartup(false); 
    bean.afterPropertiesSet(); 
    return (DataSource)bean.getObject(); 
} 

Quand je mets La propriété setLookupOnStartup du bean étant true, l'application a réussi à obtenir la connexion à la base de données. Cependant, je vois encore le problème lorsque l'application tente de faire la recherche par JNDI, ie.,

 DataSource dataSource = 
      (DataSource) new InitialContext().lookup("java:comp/env/jdbc/myDataSource"); 

Donc, si des tests supplémentaires en utilisant la fève est couronné de succès, alors je vais probablement aller avec faire les recherches en utilisant le haricot. De plus, je suis ouvert aux suggestions s'il y a de meilleures façons de le faire.

Aussi, je crois que la configuration de la source de données devrait être stockée dans le fichier application.properties de l'application ...

jdbc.xyz.datasource.name=jdbc/DatasourceXyz 
jdbc.xyz.datasource.driver=oracle.jdbc.OracleDriver 
jdbc.xyz.datasource.url=jdbc:oracle:thin:@hostname:1521:database 
jdbc.xyz.datasource.username=someUser 
jdbc.xyz.datasource.password=*** 
+0

Où est installée votre configuration jndi? – ndrone

+0

Pourquoi auriez-vous besoin de JNDI avec un tomcat embarqué ?! –

+0

J'ai ajouté plus de détails à mon message, alors laissez-moi savoir si cela aide à répondre à votre question, ainsi que la question précédente de @ndrone. –

Répondre

0

Je ne sais pas pourquoi les recherches JNDI directes échouent lorsqu'ils sont effectués dans le cadre d'un appel de service Web SOAP Apache CXF. Cependant, les recherches effectuées à l'aide du bean JndiObjectFactoryBean fonctionnent, donc c'est ce que je vais faire avec.