Como usar o JNDI DataSource fornecido pelo Tomcat no Spring?

159

Diz-se que no artigo do Spring javadoc sobre DriverManagerDataSourceclasse, essa classe é muito simples e é recomendada

para usar um JNDI DataSource fornecido pelo contêiner. Tal DataSourcepode ser exposto como um DataSourcebean em um Spring ApplicationContext viaJndiObjectFactoryBean

A questão é: como faço para fazer isso?

Por exemplo, se eu quiser ter um DataSourcebean para acessar meu banco de dados MySQL personalizado, o que eu precisaria então? O que devo escrever na configuração de contexto, etc?

Suzan Cioc
fonte

Respostas:

302

Se estiver usando a configuração baseada em esquema XML do Spring, configure no contexto do Spring assim:

<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" />

Como alternativa, configure usando uma configuração de bean simples como esta:

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

Você pode declarar o recurso JNDI no server.xml do tomcat usando algo como isto:

<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>

E referencie o recurso JNDI no web context.xml do Tomcat da seguinte maneira:

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

Documentação de referência:

Editar: esta resposta foi atualizada para o Tomcat 8 e o Spring 4. Houve algumas alterações no nome da propriedade para a configuração do pool de recursos de fonte de dados padrão do Tomcat .

kaliatech
fonte
@skaffman Sim, mas você fornece um link para a documentação de referência do Spring.
Etienne Miret
que arquivo exatamente você quer dizer com "web context.xml do Tomcat"?
Pavel Niedoba
1
@PavelNiedoba O Tomcat usa um "contexto" para a configuração específica do aplicativo da web do tomcat. O arquivo de contexto e / ou a configuração de contexto podem ser colocados em vários locais, por isso não posso fornecer uma resposta definitiva. Um local comum é "/META-INF/context.xml". Consulte a seção "Definindo um contexto" aqui: tomcat.apache.org/tomcat-8.0-doc/config/…
kaliatech 16/15/15
Mmm ... não parece funcionar para o meu oracle db, existem diferenças com o postgresql?
Phate
1
@Phate Não há diferenças fundamentais entre Oracle e PostgreSQL no nível JDBC / JNDI / Tomcat. No entanto, o Oracle é muito diferente do PostgreSQL quando se trata de detalhes de configuração do cliente / servidor Oracle. Escopo externo da pergunta / resposta original. Sugira postar uma nova pergunta com detalhes do que você tentou, versões específicas e quaisquer mensagens de erro. Exemplo: stackoverflow.com/questions/10388137/…
kaliatech
52

Com o mecanismo JavaConfig do Spring, você pode fazer o seguinte:

@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
fonte
2
Ou use o JndiDataSourceLookup
Arend v. Reinersdorff
21

Supondo que você tenha uma definição de fonte de dados "sampleDS" dentro da configuração do tomcat, você pode adicionar as seguintes linhas ao seu applicationContext.xmlpara acessar a fonte de dados usando JNDI.

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

Você deve definir o espaço para nome e o local do esquema para o jeeprefixo 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
fonte
15

Documentação: C.2.3.1 <jee:jndi-lookup/>(simples)

Exemplo:

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

Você só precisa descobrir a que nome JNDI o seu appserver ligou a fonte de dados. Isso é totalmente específico do servidor, consulte os documentos em seu servidor para descobrir como.

Lembre-se de declarar o jeeespaço para nome na parte superior do seu arquivo beans, conforme descrito em C.2.3 O esquema jee .

skaffman
fonte
8

Outro recurso: em vez de server.xml, você pode adicionar a tag "Resource" em
your_application / META-INF / Context.xml (de acordo com os documentos do tomcat ), como este:

<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
fonte
5

De acordo com a página de instruções do Apache Tomcat 7 JNDI Datasource , deve haver uma configuração de recurso no 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>

Isso funciona para mim

Antonio
fonte
4

Na sua aula de primavera, você pode injetar um feijão anotado como

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

e você adiciona isso no seu context.xml

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

Você pode declarar o recurso JNDI no server.xml do tomcat 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"/>

voltar a context.xml de spring adicione isso

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

se, como este exemplo, você estiver injetando conexão com o banco de dados, verifique se o jar do MySQL está presente no diretório lib do tomcat, caso contrário, o tomcat não poderá criar o pool de conexões do banco de dados MySQL.

Toumi
fonte
1

Achei esta solução muito útil de uma maneira limpa para remover completamente a configuração xml.

Por favor, verifique esta configuração de banco de dados usando JNDI e framework Spring. http://www.unotions.com/design/how-to-create-oracleothersql-db-configuration-using-spring-and-maven/

Neste artigo, ele explica como é fácil criar uma configuração de banco de dados com base na configuração do banco de dados jndi (db / test). Depois de concluir a configuração, todos os repositórios db serão carregados usando este jndi. Eu achei útil. Se o @Pierre tiver problemas com isso, entre em contato. É uma solução completa para escrever a configuração de banco de dados.

user3892286
fonte
neste artigo, ele explica como é fácil criar uma configuração de banco de dados com base na configuração do banco de dados jndi (db / test). Depois de concluir a configuração, todos os repositórios db serão carregados usando este jndi. Eu achei útil. Se a @Pierre tiver problemas com isso, entre em contato. É uma solução completa para escrever a configuração de banco de dados.
user3892286
neste artigo, ele explica como é fácil criar uma configuração de banco de dados com base na configuração do banco de dados jndi (db / test). Depois de concluir a configuração, todos os repositórios db serão carregados usando este jndi. Eu achei útil. Se a @Pierre tiver problemas com isso, entre em contato. É uma solução completa para escrever a configuração de banco de dados.
Sergio A.