java - example - spring jndi datasource oracle
Debería configurar las propiedades de conexión de la base de datos en server.xml o context.xml (5)
Estoy intentando configurar las propiedades de conexión de la base de datos usando JNDI para una aplicación web Spring.
Estoy considerando dos enfoques de la siguiente manera:
Enfoque 1:
En la configuración de Spring, puede tener algo como:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/facs"/>
Luego, en su archivo webapp / META-INF/context.xml también debería tener algo similar:
<?xml version=''1.0'' encoding=''utf-8''?>
<!-- antiResourceLocking="true" -->
<Context path="/podd-apn"
reloadable="true"
cachingAllowed="false"
antiResourceLocking="true"
>
<Resource name="jdbc/facs"
type="javax.sql.DataSource" username="${database.username}" password="${database.password}"
driverClassName="org.postgresql.Driver"
url="${database.url}"
maxActive="8" maxIdle="4"
global="jdbc/facs"
/>
</Context>
Y en su web.xml debe hacer algo como:
<!-- JNDI -->
<resource-ref>
<description>FACs Datasource</description>
<res-ref-name>jdbc/facs</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Enfoque 2:
Configuración en el contexto de primavera de esta manera:
<jee:jndi-lookup id="dbDataSource"
jndi-name="jdbc/DatabaseName"
expected-type="javax.sql.DataSource" />
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="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"/>
</GlobalNamingResources/>
Y haga referencia al recurso JNDI desde el contexto web de Tomcat.xml de la siguiente manera:
<ResourceLink name="jdbc/DatabaseName"
global="jdbc/DatabaseName"
type="javax.sql.DataSource"/>
Mi pregunta es ¿dónde está el mejor lugar para mantener las propiedades de la base de datos? ¿Deberían colocarse en server.xml o context.xml ?
Además, si tengo 2 bases de datos, ¿debería usar dos configuraciones?
Además, ¿es recomendable colocarlos directamente en server.xml o context.xml? ¿O debo configurarlo a través de la consola de la GUI de Tomcat Manager?
¡Gracias!
Prefiero el Método 2 (poner todo (no solo algún atributo en la configuración),
pero en lugar de colocarlos en el server.xml
o global context.xml
, debe colocarlo en el específico de la aplicación.xml.default context.xml.default
YOUR_APP.xml
en su tomcat.
El archivo YOUR_APP.xml
se encuentra en $catalinaHome/conf/<engine>/<host>
(por ejemplo conf / Catalina / localhost / YOUR_APP.xml).
La configuración específica de la aplicación YOUR_APP.xml
solo está disponible para la aplicación específica.
Prefiero un tercer enfoque que tome lo mejor del Método 1 y el Método 2 descritos por el usuario1016403 .
Enfoque 3
- Guarde las propiedades de la base de datos en el
server.xml
-
server.xml
referencia a las propiedades de la base de datosserver.xml
desde la aplicación webMETA-INF/context.xml
Enfoque 3 beneficios
Si bien el primer punto es útil por razones de seguridad, el segundo punto es útil para hacer referencia al valor de las propiedades del servidor desde la aplicación web, incluso si los valores de las propiedades del servidor cambian.
Además, al desvincular las definiciones de recursos en el servidor de su uso por la aplicación web, dicha configuración puede escalarse en organizaciones con diversas complejidades donde diferentes equipos trabajan en diferentes niveles / capas: el equipo de administradores del servidor puede trabajar sin conflicto con el equipo de desarrolladores si el administrador comparte el mismo Nombre JNDI con el desarrollador de cada recurso.
Enfoque 3 implementación
Defina el nombre JNDI jdbc/ApplicationContext_DatabaseName
.
Declare las propiedades y valores de jdbc/ApplicationContext_DatabaseName
en Tomcat''s server.xml
usando algo como esto:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContext_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"/>
</GlobalNamingResources/>
Enlace las propiedades de jdbc/ApplicationContext_DatabaseName
de la aplicación web META-INF/context.xml
mediante un contexto JNDI de aplicación privada java:comp/env/
specified en el atributo name
:
<Context path="/ApplicationContext" ... >
<!--
"global" attribute links to GlobalNamingResources in the ${catalina.base}/conf/server.xml (server administrator team)
"name" attribute is relative to the application-private JNDI context java:comp/env/ and is looked up from the java web application (application developer team)
-->
<ResourceLink global="jdbc/ApplicationContext_DatabaseName" name="jdbc/DatabaseName" type="javax.sql.DataSource"/>
</Context>
Finalmente, para usar el recurso JNDI, especifique el nombre JNDI jdbc/DatabaseName
en el descriptor de implementación de la aplicación web:
<resource-ref>
<description>DatabaseName''s Datasource</description>
<res-ref-name>jdbc/DatabaseName</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
y en el contexto de primavera:
<jee:jndi-lookup id="DatabaseNameDataSource"
jndi-name="jdbc/DatabaseName"
expected-type="javax.sql.DataSource" />
Enfoque 3 inconvenientes
Si el nombre JNDI se cambia, tanto el server.xml
como el META-INF/context.xml
tendrán que ser editados y será necesario implementarlo; sin embargo, este escenario es raro.
Enfoque 3 variaciones
Muchas fuentes de datos utilizadas por una aplicación web
Simplemente agregue configuraciones al server.xml
de Tomcat:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContext_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContext_DatabaseName2" ... />
...
</GlobalNamingResources/>
Agregue la aplicación web de enlace META-INF/context.xml
mediante un contexto JNDI de aplicación privada java:comp/env/
specified en el atributo de name
:
<Context path="/ApplicationContext" ... >
<ResourceLink global="jdbc/ApplicationContext_DatabaseName1" name="jdbc/DatabaseName1" ... />
<ResourceLink global="jdbc/ApplicationContext_DatabaseName2" name="jdbc/DatabaseName2" ... />
...
</Context>
Finalmente, agregue el uso de recursos JNDI en el descriptor de implementación de la aplicación web:
<resource-ref>
<description>DatabaseName1''s Datasource</description>
<res-ref-name>jdbc/DatabaseName1</res-ref-name> ...
</resource-ref>
<resource-ref>
<description>DatabaseName2''s Datasource</description>
<res-ref-name>jdbc/DatabaseName2</res-ref-name> ...
</resource-ref>
...
y en el contexto de primavera:
<jee:jndi-lookup id="DatabaseName1DataSource"
jndi-name="jdbc/DatabaseName1" ... />
<jee:jndi-lookup id="DatabaseName2DataSource"
jndi-name="jdbc/DatabaseName2" ... />
...
Muchas fuentes de datos utilizadas por muchas aplicaciones web en el mismo servidor
Simplemente agregue la configuración al server.xml
de Tomcat:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextX_DatabaseName2" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName2" ... />
...
</GlobalNamingResources/>
la configuración de los demás debe ser deducible del caso de variación anterior.
Muchas fuentes de datos a la misma base de datos utilizada por muchas aplicaciones web en el mismo servidor
En tal caso, las configuraciones server.xml
de Tomcat les server.xml
:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
termina en dos aplicaciones web diferentes META-INF/context.xml
como:
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
y, como:
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
entonces, alguien podría estar preocupado por el hecho de que el mismo name="jdbc/DatabaseName"
es buscado, y luego utilizado, por dos aplicaciones diferentes implementadas en el mismo servidor: esto no es un problema porque el jdbc/DatabaseName
es una aplicación- contexto JNDI privado java:comp/env/
, entonces ApplicationContextX
utilizando java:comp/env/
no puede (por diseño) buscar el recurso vinculado a global="jdbc/ApplicationContextY_DatabaseName"
.
Por supuesto, si te sientes más relajado sin esta preocupación, puedes usar una estrategia de nombres diferente como:
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/applicationXprivateDatabaseName" ... />
</Context>
y, como:
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/applicationYprivateDatabaseName" ... />
</Context>
También puede usar el soporte URL JNDI para diferentes configuraciones de aplicaciones para prueba, prueba de integración, producción.
<Context>
...
<Resource auth="Container" factory="com.benasmussen.jndi.url.URLFactory"
name="url/MyUrl" type="java.net.URL" url="file:///your/path/to/file"/>
...
</Context>
<jee:jndi-lookup id="myUrl" jndi-name="java:comp/env/url/MyUrl" expected-type="java.net.URL" />
Consulte el Soporte de JNDI URL del proyecto GitHub para habilitar el soporte de URL JNDI para los servidores Tomcat.
paso 1: context.xml
<Context path="/projectname">
<Resource auth="Container"
driverClassName="com.mysql.jdbc.Driver"
logAbandoned="true"
maxActive="100" ``
maxIdle="30"
maxWait="10000"
name="refname"
removeAbandoned="true"
removeAbandonedTimeout="60"
type="javax.sql.DataSource"
url="jdbc:mysql://localhost:8080/dbname"
username="root"
password="root"/>
</Context>
Paso 2: web.xml
<resource-ref>
<description>DB Connection</description>
<res-ref-name>refname</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Paso 3: crea una clase para obtener conexión
Connection connection = null;
Context context = (Context) new InitialContext().lookup("java:comp/env");
DataSource ds = (DataSource) context.lookup("refname");
connection = ds.getConnection();
Todo está listo
Enfoque 4
En lugar de usar JNDI, trabajo con archivos .properties
y compilo un objeto complejo durante la inicialización del programa en vez del tiempo de configuración.
Ya usas Spring y es fácil construir DataSource
de la siguiente manera:
<context:property-placeholder location="classpath:app.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@${db.host}:${db.port}:${db.user}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.pass}"/>
</bean>
Estoy totalmente de acuerdo con Ralph en el uso del descriptor de implementación en $CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml
pero en su lugar JNDI me gusta el archivo de valor-clave simple.
Con Spring inyectando las propiedades anteriores en los campos de frijol es fácil:
@Value("${db.user}") String defaultSchema;
en lugar de JNDI:
@Inject ApplicationContext context;
Enviroment env = context.getEnvironment();
String defaultSchema = env.getProperty("db.user");
Tenga en cuenta también que EL permite esto (valores predeterminados y sustitución recursiva profunda):
@Value(''${db.user:testdb}'') private String dbUserName;
<property name=''username'' value=''${db.user.${env}}''/>
Para externalizar el archivo .properties
utilizo Tomcat 7 moderno que tiene org.apache.catalina.loader.VirtualWebappLoader :
<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="/srv/web/app/"/>
Por lo tanto, sus devops llenan virtualClasspath
con rutas completas externas locales separadas por aplicación y ponen app.properties
locales en ese directorio.
Ver también:
- Agregar un directorio a tomcat classpath
- ¿Puedo crear una ruta de clases personalizada por aplicación en Tomcat
- Externalización de la configuración de la aplicación de Tomcat desde el archivo .war
- Cómo leer un archivo de propiedades fuera de mi contexto de aplicaciones web en Tomcat
- Configure Tomcat para usar el archivo de propiedades para cargar información de conexión de BD
- Externalizar la configuración de Tomcat