views:

438

answers:

2

My build path in Eclipse looks like this:

ProjectName
   -- WEB-INF
      -- classes
         -- myClass.class
      -- configs
         -- myConfig.xml

My absolute path to the config currently looks like this:

C:\Development\Java\ProjectName\WEB-INF\configs\myConfig.xml

I'm using JAXB for the binding, and it is expecting a FileInputStream. The FileInputStream needs to be a stream for the XML config file. However, I can't figure out how to get the FileInputStream for my config, and I keep getting a FileNotFoundException.

I want this config to be loaded in such a way that someone doesn't have to hardcode the path to the config because I plan on releasing the project open source. I see a lot of examples where someone just hardcodes the full absolute path, but I need it to be something more flexible "like" this:

new FileInputStream("/WEB-INF/configs/myConfig.xml");

Thanks!

+2  A: 

I'd recommend putting that myConfig.xml in the WEB-INF/classes directory instead and loading it via the class loader, since it's in the classpath. Calling getResourceAsStream() on the servlet context will return an InputStream that you can use. It's relative to the context root, so you can pick up that WAR and put it anywhere - your code will still work.

duffymo
Yeah, I've seen that suggestion a few different times, and I'm wondering if that is the best way to do it so that I don't have to deal with this anymore.
hal10001
hey @duffymo, I disagree with that. More often than not we want to separate the code under WEB-INF/classes from configuration files, because they are deployed differently and sometimes have different meanings (e.g., the client knows that he can change configuration files under WEB-INF/config, but he can't touch anything under classes/ because that belongs to us. It's perfectly legitimate to keep resources under WEB-INF, like jsp fragments, tld files, etc.
Yoni
Perfectly legitimate to keep JSPs and such under WEB-INF - your app isn't reading any JSPs during its operation. I wouldn't put things that have to be read by the app under WEB-INF; those belong in WEB-INF/classes, accessed by the class loader.
duffymo
+3  A: 

You can get the input stream of relative paths under WEB-INF fairly easily with ServletContext.getResourceAsStream() method (javadoc here) and its variants.

For example, in your selvlet code you can do this:

getServletContext().getResourceAsStream("/WEB-INF/configs/myConfig.xml") // your file
getServletContext().getResource("/WEB-INF") // URL to WEB-INF dir
Yoni
I tried this first, but it does not work. I believe both of those begin by looking at the classpath root, and since the configs directory is not on the runtime classpath, I keep getting null.
hal10001
hey @hal, your belief is wrong :) those methods look in the classpath onlywhen you invoke them on Class object or ClassLoader object. When used on servletContext, they do what I described above - that is exactly their intention, you can read it in the javadocs
Yoni
It wouldn't be the first time I've been wrong :) Do you think it might have something to do with how Eclipse handles what it considers to be the ServletContext? I also did some research, and some developers mentioned that the /WEB-INF directory is read-only. Would that be causing an issue?
hal10001
@hal10001, I am not aware of WEB-INF being read-only. It is hidden from the outside world (the browser), so perhaps some people refer to it as read-only, however in practice it is not even readable from the outside. Inside your code, however, I believe that you can read and write files in there, just like anywhere else in the file system.
Yoni
Personally, I don't think clients should be mucking around with anything in your app. I usually package mine in a WAR file, and that's sealed from the point of view of others. If something in configuration has to be changed, I don't want just anybody to be able to do it when they feel like it. It's a recipe for doing great damage where I work.
duffymo