Basic JConfig Questions

Hello

I realize JConfig has been around for years but it is new to me. I understand why a developer would want to use it but I am struggling with a few concepts that I was hoping I could get some help with.

The code to load the config.xml file is…


private static final Configuration configuration =
        ConfigurationManager.getConfiguration();

Where should this code be located for a web site?

For example, I have a BaseServlet that all my servlets extend. Should this code be located in that BaseServlet? The downside to this approach is that for every servlet request will have I\O related to retrieving the config.xml. The location for my log4j configuration file will be located in here so I assume each servlet will need to use it. Just curious if this is how others load the config.xml.

Is there a more efficient way? For example, could I load it into memory so there is not an I/O hit to load the XML file each time it is needed? If I do this, how do I deploy a new config.xml file?

Thanks in advance for your time and knowledge.

This code excerpt from ConfigurationManager.getConfiguration(String name) tells us what you want to know


        if (configurations.containsKey(name)) {            
            return (Configuration) configurations.get(name);

Namely that once the manager loads the config, it holds on to a copy of it and doesn’t need to reload the file every time you ask for it.

It is instrumental to note that getConfiguration() simply calls getConfiguration( String name ) with “default” as the arg (which corresponds to the manager loading the default ‘config.xml’ file)

To deploy an updated config.xml on the fly, call .reload( “default” ) (or whatever you named your file) - or, if on the fly support isn’t needed, simply restart your app.

edit: It occured to me to check reload…turns out it’s not static so you’ll need to retrieve the ConfiguirationManager instance with ConfigurationManager.getInstance() before you call reload.

Or, you could do it all at once with ConfigurationManager.getInstance().reload( “whatever” );

Rushiku, thank you very much for your response. Just to show understanding, I would like to reiterate. I could add the code to get the configuration file from my BaseServlet which almost every servlet I use extends and there will not be much for an IO hit. This is because the configuration manager will only load the file if it does not have an instance of it. That makes sense… thank you for pointing that out.

I understand the .reload code you are pointing out but I am curious where a developer would put that code in an application. Reloading the config file does not occur that often so do you write a separate servlet for this. Then, when a new config file is FTPd to the server, you access this servlet to reload the config.xml file? It is probably obvious, but I have never deployed a Java project in a host environment. I am thinking of using GoDaddy, so I am trying to figure out how I am going to provide mainteneance to the site… trying to develop some good habits. Any feedback you can provide is appreciated.

For remote hosting, yes, I would go with a separate servlet to issue the reload.

Let’s call it AdminServlet, which would have a corresponding admin.jsp. On admin.jsp you could include all the various admin level tasks that you’ll need to do, such as reloading the config.

admin.jsp should be an ‘unlinked’ page, in that you have to manually enter the address to get to it, and require some sort of login.

Good point… thank you for the feedback

I am having an issue loading the config.xml file.

I have tried placing the file in 2 locations in an Eclipse Dynamic Web Project where I am deploying using Tomcat 5.5:

WebContent/conf/config.xml
WebContent/WEB-INF/config.xml

But neither of these locations work when I use this code:

private static final Configuration configuration =
ConfigurationManager.getConfiguration();

I have also tried:

private static final Configuration configuration =
ConfigurationManager.getConfiguration( “config.xml” );

I looked up the javadoc and saw a load() method but it also requires a configuration handler and I am not sure what I would provide for that.

To get this to work, where should I place the config.xml file?

Also, I thought about trying to use the web.xml to determine where the config.xml location is but then again, I could not figure out how to load the file.

Any feedback you can provide would be appreciated.

I’ve never actually used jConfig (you introduced me to it :wink: ), so I’ve been curious how this detail would work out.

Reading through some more of the source yields this:

When you say “private static final Configuration configuration =
ConfigurationManager.getConfiguration();” getConfiguration checks its internal set of configs to see if yours has already been loaded, I guess we knew that already, if it doesn’t find it, it starts the process of getting it off the disk.

First it creates an InputStreamHandler, which creates a ResourceLocator (both are jconfig classes). The ResourceLocator checks all the locations listed on the env variable ‘classpath’, then uses ResourceLocator.class.getResource(String) to look around some more. I wasn’t familiar with .class.getResource, so I glossed over it. Turns out it’s a method defined in Class, the methods of which are available to any Object by using [Your Object Name].class.[method name]. Hmm, this paragraph does nothing to advance my story as it was a dead end, well, getting there is half the fun.

I searched the net for a while and read some more jconfig code…I was about to give up when I stumbled on this bit of code at the end of the constructor for ResourceLocator:


		if ( name != null && !name.equals("config.xml") ) {
        throw new IOException(
            "Resource '"
                + name
                + "' could not be found in "
                + "the CLASSPATH ("
                + System.getProperty("java.class.path")
                + "), nor could it be located by the classloader responsible for the "
                + "web application (WEB-INF/classes)"
                + msg);
		}

Long story short, I’m guessing WEB-INF/classes should work.

Thank you very much for the feedback. I will try adding the config.xml to:

Webcontent/WEB-INF/classes

I will also have to get the source code… you have found a lot of details in there that I could definitely learn from.

At this moment, I still think there should be a way you tell the configuration manager where to look for the file. I looked through the Javadocs but I did not see any method for this. I did find the load method but that also required a configuration handler but I am not sure what that would be. Have you seen anything that allows you to tell the configuration manager where to load the config.xml from?

Another option might be to code your own Configuration Manager. Just a thought.

I thought the same thing, but wasn’t able turn anything up.

An issue to consider when ‘telling’ jconfig where to find the config.xml is that hardcoding a file path to the config, or adding a path to the classpath, kills the ‘write once, deploy everywhere’ ideal of web apps.

Given that jconfig is so specific in its error message, I’m hoping WEB-INF/classes will work.

You are right… placing the config.xml in the WEB-INF/classes directory did allow the ConfigurationManager to load the code.

Eclipse did do one thing for me that caught me off guard. When I added the classes directory under WebContent/WEB-INF/classes, Eclipse in the Java view then moved the directory under Web App Libraries (and made it no longer visible under WEB-INF). But then when I went to the Java EE view in Eclipse, the classes folder then existed again under the WEB-INF directory. In the Java EE view, the Web App Libraries section is not even visible. Maybe pointing this out means I do not understand the difference between these 2 views (which is probably true) but I did find it odd. Would you know why this occurred?

I did get a 2nd approach to work as well.

In my web.xml, I added an <init-param> to the servlet.


<servlet>
  <servlet-name>test</servlet-name>
  <servlet-class>servlet.TestServlet</servlet-class>
  <init-param>
    <param-name>config.file</param-name>
    <param-value>
      WEB-INF/config.xml
    </param-value>
  </init-param>
</servlet>

Then in my servlet class, I added this code:


String location = this.getServletContext().getRealPath(
		this.getServletConfig().getInitParameter("config.file"));

File file = new File(location);
XMLFileHandler handler = new XMLFileHandler();
handler.setFile(file);
ConfigurationManager configMgr = ConfigurationManager.getInstance();
try {
	configMgr.load(handler, "ConfigName");
	config = configMgr.getConfiguration( "ConfigName" );
} catch (ConfigurationManagerException e) {
	e.printStackTrace();
}

Using this approach loads the configuration file as well. This approach also allows for a person to place the config.xml file any where they want. Plus, since I am not sure how the classes directory works in a Java project, especially when I end up deploying to a hosting server, this approach kind of makes sense.

The draw back is that I have to add the init-param to every servlet mapping in the web.xml file that could potentially need to access the config.xml jconfig configuration file. Do you know if there is a way I could only add this once to the web.xml file as an init-param and allow it to be accessed by multiple serlvets?

Thanks for your time and knowledge in exploring jconfig. I am going to use this as my web application configuration file and based on more research and your response will dictate how I end up implementing it.

To add one web.xml param that will be available to any servlet, add a context-param as shown here (how to retrieve it is also shown)

I never got into Eclipse, preferring to ‘do it myself’ by using Ant. As such, I can’t really address what Eclipse is doing or its different views.

However, I can tell you that the classes directory is an integral part of a Java web app. classes is where your, well, classes will appear upon deployment. eg: if you write my.servlets.HelloWorldServlet for your web app named MyWebApp, it will appear in [Path to web apps]/MyWebApp/WEB-INF/classes/my/servlets.

The only time your web app won’t have a classes directory is if you jar all your app’s code, which would put your code into WEB-INF/lib, eliminating the need for the classes directory. However, just because you jar your code doesn’t mean you can’t have a classes - ie: despite ‘jarring’ my code, I still need a classes directory for my hibernate config. (for the same reasons that the jconfig config needs to appear in classes, in retrospect).

I think it’s great you found a way to work around the apparent limitation of jconfig, but, personally, I always feel better using a tool the way it was ‘meant’ to be used - having to constantly retrieve that context param is going to get old. If you place config.xml in classes, jconfig will ‘just work’ taking some load off of you and simplifying your code in the process.

Thank you for the information. I agree with your approach about trying to use a tool as it was intended… that makes sense. I also appreciate the explanation on the classes directory and web.xml. This has been a great thread for me… I learned about jConfig which was my goal but I also learned more about the workings of a Java web application.

On a side note… I have enjoyed your Chris Farley aka Matt Foley reference… “A van down by the river”.

It’s been good for me as well, learned about a new tool :slight_smile:

Ah, Matt Foley, the greatest motivational speaker to have ever lived. :wink:
(I was feeling a bit down and out back in Dec 2003, hence the van reference, never updated it)

Just wanted to know if there is any approach to fetch the details of file from the classpath.