5

Simplified situation:

  • I have 1 Tomcat container and 1 WAR which uses a database.
  • The database configuration sits in a properties file (in the war).
  • I deployed the WAR 2 times, one webapp on contextpath /a and one webapp on contextpath /b.
  • Both webapps now point to the same database (same cfg).

What I want is that each webapp points to a different database. So, the webapp on /a points to database A and the the webapp on /b points to database B.

How would you solve this? (without splitting the war itself)

codesmith
  • 1,381
  • 3
  • 20
  • 42
  • 1
    Why not change the configuration files of each war to point to different databases? – Luke Bajada Dec 08 '17 at 10:18
  • 1
    @LukeBajada: I don't *like* to build 2 wars, just because one or two properties differ. – codesmith Dec 08 '17 at 10:30
  • @Henry: env vars or system properties are system wide and thus container wide and thus not war-specific. Please explain. – codesmith Dec 08 '17 at 10:30
  • @codesmith yes, you are right, would not work either. I was thinking about the case where the same war is deployed in different Tomcat instances. – Henry Dec 08 '17 at 10:33
  • https://stackoverflow.com/questions/16946814/different-environment-variables-per-war-in-tomcat https://stackoverflow.com/questions/36353040/how-to-run-two-war-files-with-different-spring-profiles-on-a-tomcat-server – codesmith Dec 08 '17 at 10:50

3 Answers3

9

You can do it by Tomcat's context.xml configuration without splitting your code.

You can define two context for example /a and /b and two different global data sources "sharedDataSourceA" and "sharedDataSourceB". You can bind different global data sources to these contexts with same name like "appDataSource".

<GlobalNamingResources>
  ...
  <Resource name="sharedDataSourceA"
            global="sharedDataSourceA"
            type="javax.sql.DataSource"
            factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
            alternateUsernameAllowed="true"
            username="bar"
            password="barpass"
            ...
<Resource name="sharedDataSourceB"
            global="sharedDataSourceB"
            type="javax.sql.DataSource"
            factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
            alternateUsernameAllowed="true"
            username="bar"
            password="barpass"
            ...
  ...
</GlobalNamingResources>

<Context path="/a"...>
  ...
  <ResourceLink
            name="appDataSource"
            global="sharedDataSourceA"
            type="javax.sql.DataSource"
            factory="org.apache.naming.factory.DataSourceLinkFactory"
            username="foo"
            password="foopass"
  ...
</Context>
<Context path="/b"...>
  ...
  <ResourceLink
            name="appDataSource"
            global="sharedDataSourceA"
            type="javax.sql.DataSource"
  ...
</Context>

Then in your code you can bind datasource to "appDataSource" by jndi lookup. Deploy the same war to /a and /b . They will work on different databases.

Mehmet Sunkur
  • 2,373
  • 16
  • 22
2

You could get the current context programmatically and configure the datasource according to the obtained value. For example using javax.servlet.ServletContext.getContextPath().

You could also load a properties file according to context name.

LMC
  • 10,453
  • 2
  • 27
  • 52
0

getContextPath() was suggested, and here is a technique to use it with getInitParameter()

As an example, if you had two contexts: "/dev" and "/prod" - both indentical - and you set up your web.xml file with entries like:

<context-param>
    <param-name>database_ip_prod</param-name>
    <param-value>192.168.1.10</param-value>
</context-param>

<context-param>
    <param-name>database_ip_dev</param-name>
    <param-value>127.0.0.1</param-value>
</context-param>

And with a method like this:

public String getContextInitParam(
        javax.servlet.ServletContext context, String key) {
    key += context.getContextPath().replace("/","_");
    return context.getInitParameter(key);
}

A call like this from a jsp or servlet:

getContextInitParam(request.getServletContext(), "database_ip");

would return 192.168.1.10 on the /prod context, and 127.0.0.1 on the /dev context.

John T
  • 325
  • 2
  • 8