¿Cómo usar JNDI DataSource proporcionado por Tomcat en Spring?

159

Se dice que en el artículo de Spring Javadoc sobre la DriverManagerDataSourceclase, que esta clase es muy simple y que se recomienda

para usar un JNDI DataSource proporcionado por el contenedor. Tal DataSourcepuede ser expuesto como un DataSourcebean en un Spring ApplicationContext víaJndiObjectFactoryBean

La pregunta es: ¿cómo puedo lograr esto?

Por ejemplo, si deseo tener DataSourcebean para acceder a mi base de datos MySQL personalizada, ¿qué necesitaría entonces? ¿Qué debo escribir en la configuración de contexto, etc.?

Suzan Cioc
fuente

Respuestas:

302

Si utiliza la configuración basada en el esquema XML de Spring, configure en el contexto de Spring de esta manera:

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
...
<jee:jndi-lookup id="dbDataSource"
   jndi-name="jdbc/DatabaseName"
   expected-type="javax.sql.DataSource" />

Alternativamente, configure usando una configuración de bean simple como esta:

<bean id="DatabaseName" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/DatabaseName"/>
</bean>

Puede declarar el recurso JNDI en server.xml de tomcat usando algo como esto:

<GlobalNamingResources>
    <Resource name="jdbc/DatabaseName"
              auth="Container"
              type="javax.sql.DataSource"
              username="dbUser"
              password="dbPassword"
              url="jdbc:postgresql://localhost/dbname"
              driverClassName="org.postgresql.Driver"
              initialSize="20"
              maxWaitMillis="15000"
              maxTotal="75"
              maxIdle="20"
              maxAge="7200000"
              testOnBorrow="true"
              validationQuery="select 1"
              />
</GlobalNamingResources>

Y haga referencia al recurso JNDI de Tomcat's web context.xml de esta manera:

  <ResourceLink name="jdbc/DatabaseName"
   global="jdbc/DatabaseName"
   type="javax.sql.DataSource"/>

Documentación de referencia:

Editar: esta respuesta se ha actualizado para Tomcat 8 y Spring 4. Se han realizado algunos cambios en el nombre de la propiedad para la configuración predeterminada del grupo de recursos de datos de Tomcat .

kaliatech
fuente
@skaffman Sí, pero proporciona un enlace a la documentación de referencia de Spring.
Etienne Miret
¿Qué archivo quieres decir exactamente con "Tomcat's web context.xml"?
Pavel Niedoba
1
@PavelNiedoba Tomcat utiliza un "contexto" para la configuración de aplicaciones web específicas de tomcat. El archivo de contexto y / o la configuración de contexto se pueden colocar en varias ubicaciones, por lo que no puedo darle una respuesta definitiva. Una ubicación común es "/META-INF/context.xml". Consulte la sección "Definir un contexto" aquí: tomcat.apache.org/tomcat-8.0-doc/config/…
kaliatech
Mmm ... no parece funcionar para mi oráculo db, ¿hay alguna diferencia con postgresql?
Phate
1
@Phate No hay diferencias fundamentales con Oracle vs PostgreSQL en el nivel JDBC / JNDI / Tomcat. Sin embargo, Oracle es muy diferente de PostgreSQL cuando se trata de detalles de configuración de cliente / servidor de Oracle. Fuera del alcance de la pregunta / respuesta original. Sugiera publicar una nueva pregunta con detalles de lo que ha intentado, versiones específicas y cualquier mensaje de error. Ejemplo: stackoverflow.com/questions/10388137/…
kaliatech
52

Con el mecanismo SpringConfig de Spring, puede hacerlo así:

@Configuration
public class MainConfig {

    ...

    @Bean
    DataSource dataSource() {
        DataSource dataSource = null;
        JndiTemplate jndi = new JndiTemplate();
        try {
            dataSource = jndi.lookup("java:comp/env/jdbc/yourname", DataSource.class);
        } catch (NamingException e) {
            logger.error("NamingException for java:comp/env/jdbc/yourname", e);
        }
        return dataSource;
    }

}
Abdull
fuente
2
O utilice el JndiDataSourceLookup
Arend v. Reinersdorff
21

Suponiendo que tiene una definición de fuente de datos "sampleDS" dentro de su configuración de tomcat, puede agregar las siguientes líneas a su applicationContext.xmlpara acceder a la fuente de datos utilizando JNDI.

<jee:jndi-lookup expected-type="javax.sql.DataSource" id="springBeanIdForSampleDS" jndi-name="sampleDS"/>

Debe definir el espacio de nombres y la ubicación del esquema para el jeeprefijo usando:

xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"
melihcelik
fuente
15

Documentación: C.2.3.1 <jee:jndi-lookup/>(simple)

Ejemplo:

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource"/>

Solo necesita averiguar a qué nombre JNDI ha vinculado su servidor de aplicaciones el origen de datos. Esto es completamente específico del servidor, consulte los documentos en su servidor para averiguar cómo.

Recuerde declarar el jeeespacio de nombres en la parte superior de su archivo de beans, como se describe en C.2.3 El esquema jee .

skaffman
fuente
8

Otra característica: en lugar de server.xml, puede agregar la etiqueta "Resource" en
your_application / META-INF / Context.xml (de acuerdo con los documentos de tomcat ) de esta manera:

<Context>
<Resource name="jdbc/DatabaseName" auth="Container" type="javax.sql.DataSource"
  username="dbUsername" password="dbPasswd"
  url="jdbc:postgresql://localhost/dbname"
  driverClassName="org.postgresql.Driver"
  initialSize="5" maxWait="5000"
  maxActive="120" maxIdle="5"
  validationQuery="select 1"
  poolPreparedStatements="true"/>
</Context>
Evgen
fuente
5

De acuerdo con la página de instrucciones de Apache Tomcat 7 JNDI Datasource, debe haber una configuración de recursos en web.xml:

<resource-ref>
  <description>DB Connection</description>
  <res-ref-name>jdbc/TestDB</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>

Funciona para mi

Antonio
fuente
4

En tu clase de primavera, puedes inyectar un frijol anotado como

@Autowired
@Qualifier("dbDataSource")
private DataSource dataSource;

y agrega esto en su context.xml

<beans:bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <beans:property name="jndiName" value="java:comp/env/jdbc/MyLocalDB"/>
</beans:bean>

Puede declarar el recurso JNDI en tomcat's server.xml usando

<Resource name="jdbc/TestDB" 
  global="jdbc/TestDB" 
  auth="Container" 
  type="javax.sql.DataSource" 
  driverClassName="com.mysql.jdbc.Driver" 
  url="jdbc:mysql://localhost:3306/TestDB" 
  username="pankaj" 
  password="pankaj123" 

  maxActive="100" 
  maxIdle="20" 
  minIdle="5" 
  maxWait="10000"/>

volver a context.xml de spring agregar esto

<ResourceLink name="jdbc/MyLocalDB"
                global="jdbc/TestDB"
                auth="Container"
                type="javax.sql.DataSource" />

si, como este ejemplo, está inyectando una conexión a la base de datos, asegúrese de que el jar de MySQL esté presente en el directorio tomcat lib, de lo contrario, tomcat no podrá crear el grupo de conexiones de la base de datos MySQL.

Toumi
fuente
1

Encontré esta solución muy útil de una manera limpia para eliminar completamente la configuración xml.

Compruebe esta configuración de base de datos utilizando JNDI y Spring Framework. http://www.unotions.com/design/how-to-create-oracleothersql-db-configuration-using-spring-and-maven/

En este artículo, explica lo fácil que es crear una configuración de db basada en la configuración de la base de datos jndi (db / test). una vez que haya terminado con la configuración, todos los repositorios de db se cargan usando este jndi. Encontré útil. Si @Pierre tiene problemas con esto, avíseme. Es una solución completa para escribir la configuración de db.

usuario3892286
fuente
en este artículo, explica lo fácil que es crear una configuración de db basada en la configuración de la base de datos jndi (db / test). una vez que haya terminado con la configuración, todos los repositorios de db se cargan usando este jndi. Encontré útil. Si @Pierre tiene problemas con esto, avíseme. Es una solución completa para escribir la configuración de db.
user3892286
en este artículo, explica lo fácil que es crear una configuración de db basada en la configuración de la base de datos jndi (db / test). una vez que haya terminado con la configuración, todos los repositorios de db se cargan usando este jndi. Encontré útil. Si @Pierre tiene problemas con esto, avíseme. Es una solución completa para escribir la configuración de db.
Sergio A.