Moving configuration into its own modulePosted: 18 November 2009
For a long time the java classpath was something I only sort of understood. I think I’m finally getting a handle on it.
What is (or was) also confusing for me is how the classpath is managed with tomcat (or any other servlet container, but I’ve only used tomcat). When you look at the directories and files for a web application with tomcat you can probably figure it out; under WEB-INF are two directories, lib and classes. lib contains a bunch of jars, and classes containes your compiled java code.
You often hear that something needs to “be on the classpath.” The tomcat WEB-INF/classes directory is on the classpath. So if you have any configuration files that need to be on the classpath, you can put them in the classes directory. For example, your log4j configuration file log4j.xml, or, in my case, since I use logback, logback.xml goes in the classes directory. If you’re using spring, this is where you can put your applicationContext.xml file, and then in your web.xml you’d use
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <param-name> contextConfigLocation </param-name> <param-value> classpath:spring/applicationContext.xml, </param-value> </context-param>
I’ve created a subdirectory, spring, and put my spring configuration files in that.
When you use maven, it has this really convenient directory structure; first there is the src directory, and then in it is the directory main, then in main are two directories java and resources. In the java directory you put your java source code. The resources directory is where you put your configuration files. If you’re making a web application, when maven makes the war file it puts everything that was in the resources directory in the war’s WEB-INF/classes directory. Viola, your configuration files are “on the classpath.”
(I have a spring directory in the resources directory, src/main/resources/spring, and in it are all of my spring configuration files. That’s why there’s spring/ in front of the applicationContext.xml above.)
Here’s a diagram of a web application I’m working on, which is divided into several maven modules, and with arrows showing their dependencies.
The webapp module will be the controllers or action beans. It depends on the service module, which contains the business logic, which depends on the persistence module. Everyone depends on the api module; that’s where the interfaces are declared, and the service and persistence modules implement the interfaces. The model module is what I think of as the data transfer objects, or the domain objects; more or less dumb data POJOs with getters and setters. The classes in it are annotated with JDO persistence stuff.
So what’s the config module? Up above, when I was talking about tomcat and its classpath you may have noticed that I skipped over explaining its lib directory. Intuitively, all of the jars in the lib directory are on the classpath. But a better way of thinking about it is that the contents of the jars are on the classpath. Perhaps just then a lightbulb lit up over your head and you realized that you could put configuration files in a jar file and then put that jar file in the lib directory. Now we’re really talking viola! This next diagram is a tree listing of the config maven project.
| pom.xml | +---src | +---main | | \---resources | | | logback.xml | | | | | +---META-INF | | | jdoconfig.xml | | | | | \---spring | | applicationContext.xml | | jdo-gae-context.xml | | jdo-hsql-context.xml | | jdo-tx-context.xml | | \---target | waitlist-config-0.0.1-SNAPSHOT.jar | +---classes | | logback.xml | | | +---META-INF | | jdoconfig.xml | | | \---spring | applicationContext.xml | jdo-gae-context.xml | jdo-hsql-context.xml | jdo-tx-context.xml
Besides the pom.xml, the only thing it contains is the src/main/resources directory, where we put our configuration files. The target directory is created by maven when we do a build, compile, package, etc. And in it you can see that maven created a classes directory and copied everything from the resources directory into it. And here’s what the jar file looks like:
So now we have our configuration files neatly packaged, and our various maven modules can each depend on that, and no need to duplicate configuration files across your maven modules. In case you’re wondering why the light blue arrow is showing a dependency from the model module to the config module, that’s because sometimes I’ll add logging calls to the model and then it will need the logback.xml configuration file.