0

I use Neatbeans to create a Java Class Library Project. This class (name: TestDB.java) is to do some DataBase jobs. I wrote a "config.properties" file to config some properties. The config.properties is located in the Project folder. In my class TestDB.java:

Properties properties = new Properties(System.getProperties());
String configFile = "config.properties";
properties.load(new FileInputStream(configFile));
String param1 = properties.getProperty("Postgre.Driver1");

I can use a test case to get the property, That's OK.

When I build this project and create a jar file. I want another web application to use this jar file to do some DB jobs. I already include the jar in my webapp and bulid a webproj.war. When I place this webproj.war to Tomcat and run the webapp. I can't get the property because I don't know which folder in the Tomcat webapp to place the config.properties. Anyone can help me to solve this question ?

Tom Cheng
  • 1,299
  • 4
  • 14
  • 16

1 Answers1

1

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.

Community
  • 1
  • 1
Nick Holt
  • 33,455
  • 4
  • 52
  • 58