Sorry for the long answer, but I'm trying to cover the background as I think your question is a little bit confused.
This answer tries to clarify your understanding of web-apps and reusability a little more generally.
First, it's important to understand that applications typically have to run in multiple environments - dev, sit, uat, production, etc. If you include environment specifics in your binary (jar or war) that means you can only use that binary in a single environment.
The original J2EE assumption was that these environment specifics would be managed by the container (Tomcat in this case). This is what the answer referenced in the first comment of your question is doing. Basically the container provides resources registered in JNDI, which your application can look up.
Now, I think it's fair to say, the J2EE folks where wide of the mark with some of the features, the JNDI resource mechanism being one instance of this, which isn't commonly used these days (at least not in the applications I'm used to).
Now, to try and answer your question.
The first important thing to recognise is that the reason for putting code into a seperate jar is to make it reusable. Since Spring burst onto the scene, one of the fundimental ways to achieve reusability is with dependency injection. Spring aside, dependency injection is nothing more complicated that passing the resources a particular object needs at the time you create that object.
For example, your TestDB
class might be instantiated as follows:
TestDB testDB = new TestDB(dataSource);
This still doesn't solve the problem of instantiating the DataSource
, however it does place this responsiblity with the code using TestDB
rather than TestDB
itself.
The simple way to instantiate the DataSource
would be include a properties file in the war's classpath (in WEB-INF/classes
), which would allow you to do the following (note the DataSource
instantiation will be database specific):
Properties properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream("config.properties"))
DataSource dataSource = new PGSimpleDataSource();
dataSource.setServerName(properties.get("database.server.name"));
...
So this gets you to the point where you're loading a properties file from within your war. However as I stated, this makes the war environment specific.
The best way I know to solve this is to use an exploded war with a symlink to the environment configuration. To do this, you use a context file which you would place in [Tomcat root]/conf/Catalina/localhost
.
For example, the given context file:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/my-app" docBase="/local/apps/my-app/war" distributable="false" allowLinking="true">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>
You would have a directory structure like this:
local
+ apps
+ my-app
+ war
+ WEB-INF
+ classes
+ env -> /local/apps/my-app/env
+ env
Where /local/apps/my-app/war/WEB-INF/classes/env
is a symlink to /local/apps/my-app/env
.
Your properties would now be loaded like this:
Properties properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream("env/config.properties"))
This gives you two releaseable components - the application and the configuration that are simply unpacked to install them.