Prefiero un tercer enfoque que toma lo mejor del
enfoque 1 y el enfoque 2 descritos por el usuario 1016403 .
Enfoque 3
- Guarde las propiedades de la base de datos en el
server.xml
- hacer referencia a las
server.xml
propiedades de la base de datos desde la aplicación webMETA-INF/context.xml
Beneficios del enfoque 3
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 cambiarán.
Además, el desacoplamiento de las definiciones de recursos en el servidor de su uso por la aplicación web hace que dicha configuración sea escalable entre organizaciones con diversa complejidad donde diferentes equipos trabajan en diferentes niveles / capas: el equipo de administradores del servidor puede trabajar sin entrar en conflicto con el equipo de desarrolladores si el administrador comparte lo mismo Nombre JNDI con el desarrollador de cada recurso.
Implementación del enfoque 3
Defina el nombre JNDI jdbc/ApplicationContext_DatabaseName
.
Declare las jdbc/ApplicationContext_DatabaseName
diversas propiedades y valores de Tomcat 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/>
Vincular las jdbc/ApplicationContext_DatabaseName
propiedades de la aplicación web META-INF/context.xml
mediante un contexto JNDI privado de la aplicación java:comp/env/
especificado en el name
atributo:
<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 utilizar 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 se cambia el nombre JNDI, tanto el server.xml
como el META-INF/context.xml
tendrán que ser editados y será necesaria una implementación; sin embargo, este escenario es raro.
Enfoque 3 variaciones
Muchas fuentes de datos utilizadas por una aplicación web
Simplemente agregue configuraciones a Tomcat's server.xml
:
<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 privado de la aplicación java:comp/env/
especificado en el name
atributo:
<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 a Tomcat's server.xml
:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextX_DatabaseName2" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName2" ... />
...
</GlobalNamingResources/>
la otra configuración 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 server.xml
configuraciones de un Tomcat como:
<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>
por lo que alguien podría estar preocupado por el hecho de que lo mismo name="jdbc/DatabaseName"
sea buscado y luego utilizado por dos aplicaciones diferentes implementadas en el mismo servidor: esto no es un problema porque jdbc/DatabaseName
es un contexto JNDI privado de la aplicación java:comp/env/
, ApplicationContextX
porjava:comp/env/
lo que al usar no se puede (por diseño) busque el recurso vinculado global="jdbc/ApplicationContextY_DatabaseName"
.
Por supuesto, si se sintió más relajado sin esta preocupación, podría usar una estrategia de nomenclatura 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>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... /> <Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
Si los recursos fueran grupos de conexiones, ¿esto le daría dos grupos separados, uno por aplicación web? Considerando que, si me vincule desde ambas aplicaciones web a un recurso, solo habría un grupo de conexiones, ¿correcto? ¿Alguna razón para preferir uno al otro? (grupos de conexiones de base de datos separados uno por aplicación web frente a un grupo de conexiones compartido por todas las aplicaciones web)? Gracias.