Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should you set up database connection properties in server.xml or context.xml

I am trying to set up the database connection properties using JNDI for a Spring web application.

I am considering two approaches as below:

Approach 1:

In your Spring configuration you may have something like:

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/facs"/> 

Then in your webapp /META-INF/context.xml file you should have something similar too:

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

And in your web.xml you should something like:

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


Approach 2:

Setup in the Spring context like this:

<jee:jndi-lookup id="dbDataSource"    jndi-name="jdbc/DatabaseName"    expected-type="javax.sql.DataSource" /> 

You can declare the JNDI resource in Tomcat's server.xml using something like this:

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

And reference the JNDI resource from Tomcat's web context.xml like this:

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


My question is where is the best place to keep database properties? Should they be placed in server.xml or context.xml?

Also, if I have 2 databases, should I use two configs?

Also, is it best practice to directly place them in either server.xml or context.xml? Or do I need to configure through Tomcat Manager GUI console?

Thanks!

like image 843
user1016403 Avatar asked Feb 25 '13 09:02

user1016403


People also ask

Where should I put context xml?

Your context. xml file should be installed in the META-INF folder of your application, as META-INF/context. xml. The META-INF folder belongs at the same level as WEB-INF (not inside it).

What is context xml used for?

context. xml file is the application deployment descriptor for the Apache Tomcat server. In a deployed application, this file is located in the META-INF folder of the web application directory or the WAR file, for example, tomcat/webapps/app-core/META-INF/context.

What is database connection properties?

The Database Connection Properties dialog lets you configure particular properties of a database connection. In the dialog, you can choose a JDBC driver or an existing JNDI resource, set up credentials, transaction isolation level, etc.

What is context xml in Tomcat?

In Tomcat, the Context Container represents a single web application running within a given instance of Tomcat. A web site is made up of one or more Contexts. For each explicitly configured web application, there should be one context element either in server. xml or in a separate context XML fragment file.


1 Answers

I prefer a third approach that takes the best from Approach 1 and Approach 2 described by user1016403.

Approach 3

  1. Save database properties on the server.xml
  2. reference the server.xml database properties from the web application META-INF/context.xml

Approach 3 benefits

While the first point is useful for security reasons the second point is useful for referencing server properties value from the web application, even if server properties values will change.

Moreover decoupling resource definitions on the server from their use by the web application makes such configuration scalable across organizations with various complexity where different teams work on different tiers/layers: the server administrators team can work without conflicting with developers team if the administrator shares the same JNDI name with the developer for each resource.

Approach 3 implementation

Define the JNDI name jdbc/ApplicationContext_DatabaseName.

Declare the jdbc/ApplicationContext_DatabaseName's various properties and values in Tomcat's server.xml using something like this:

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

Link the jdbc/ApplicationContext_DatabaseName's properties from web application META-INF/context.xml by an application-private JNDI context java:comp/env/ specified in the name attribute:

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

Finally, in order to use the JNDI resource, specify the JNDI name jdbc/DatabaseName in web application's deployment descriptor:

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

and in Spring context:

<jee:jndi-lookup id="DatabaseNameDataSource"    jndi-name="jdbc/DatabaseName"    expected-type="javax.sql.DataSource" /> 

Approach 3 drawbacks

If the JNDI name gets changed then both the server.xml and the META-INF/context.xml will have to be edited and a deploy would be necessary; nevertheless this scenario is rare.

Approach 3 variations

Many data sources used by one web application

Simply add configurations to Tomcat's server.xml:

<GlobalNamingResources>   <Resource name="jdbc/ApplicationContext_DatabaseName1" ... />   <Resource name="jdbc/ApplicationContext_DatabaseName2" ... />   ... </GlobalNamingResources/> 

Add link web application META-INF/context.xml by an application-private JNDI context java:comp/env/ specified in the name attribute:

<Context path="/ApplicationContext" ... >   <ResourceLink global="jdbc/ApplicationContext_DatabaseName1" name="jdbc/DatabaseName1" ... />   <ResourceLink global="jdbc/ApplicationContext_DatabaseName2" name="jdbc/DatabaseName2" ... />   ... </Context> 

Finally add JNDI resources usage in web application's deployment descriptor:

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

and in Spring context:

<jee:jndi-lookup id="DatabaseName1DataSource"    jndi-name="jdbc/DatabaseName1" ... /> <jee:jndi-lookup id="DatabaseName2DataSource"    jndi-name="jdbc/DatabaseName2" ... /> ... 


Many data sources used by many web application on the same server

Simply add configuration to 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/> 

the others configuration should be deducible from previous variation case.


Many data sources to the same database used by many web application on the same server

In such case a Tomcat's server.xml configurations like:

<GlobalNamingResources>   <Resource name="jdbc/ApplicationContextX_DatabaseName" ... />   <Resource name="jdbc/ApplicationContextY_DatabaseName" ... /> 

ends up in two different web applications META-INF/context.xml like:

<Context path="/ApplicationContextX" ... >   <ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/DatabaseName" ... /> </Context> 

and like:

<Context path="/ApplicationContextY" ... >   <ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/DatabaseName" ... /> </Context> 

so someone might be worried about the fact that the same name="jdbc/DatabaseName" is looked up, and then used, by two different applications deployed on the same server: this is not a problem because the jdbc/DatabaseName is an application-private JNDI context java:comp/env/, so ApplicationContextX by using java:comp/env/ can't (by design) look up the resource linked to global="jdbc/ApplicationContextY_DatabaseName".

Of course if you felt more relaxed without this worry you might use a different naming strategy like:

<Context path="/ApplicationContextX" ... >   <ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/applicationXprivateDatabaseName" ... /> </Context> 

and like:

<Context path="/ApplicationContextY" ... >   <ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/applicationYprivateDatabaseName" ... /> </Context> 
like image 99
taringamberini Avatar answered Sep 17 '22 09:09

taringamberini