Forums Register Login

Relative path of an XML file?

+Pie Number of slices to send: Send
I want to parse an XML file in a JSP application, but it doesn't work with relative filepaths.

Of course i tried the usual suspects like

but it didn't work :-(

I also copied the file directly to the server, but with no result.

My questions:
1. I use Eclipse. In which folder in the Eclipse project should the xml file be located?
2. In which folder on the Tomcat-server should the xml file be located?
3. Which would be the file path then?


1
+Pie Number of slices to send: Send
 

Daniel Zuckermann wrote:I also copied the file directly to the server, but with no result.



This makes it sound like your first attempts were trying to access a file which wasn't even on the same machine as the application server.

So could you clarify your post to explain what you tried, and what you expected your relative URLs to be relative to?
1
+Pie Number of slices to send: Send
ItDoesntWorkIsUseless

Why didn't it work? What path did you end up with? How was it different from what you expected?
+Pie Number of slices to send: Send
The absolute path that works is: "C:\\ECLIPSE_WORKSPACE\\TestApp\\xml\\data.xml ";

This path should be replaced by a relative path.

Then I extracted the absolute file path and received only a temporary Eclipse deployment folder:
C:\ECLIPSE_WORKSPACE\.metadata\.plugins\org.eclips e.wst.server.core\tmp0\wtpwebapps\TestApp\xml\data .xml

I think i must manually copy the file to some folder on the Tomcat-server, but I don't know if this approach is right.
1
+Pie Number of slices to send: Send
Wait a minute -- are you saying that the file isn't even on the server? How is the web app supposed to read it if not?
+Pie Number of slices to send: Send
I don't know if xml files are automatically copied to the server or if I have to copy them manually to some directory on the server.

As far as I know, all files are first created in the Eclipse project folder. When the application is built and started, the files are copied to some directories on the Tomcat-server. Am I right so far?
1
+Pie Number of slices to send: Send
As usual, relying on an IDE to deploy makes things 10x more complicated than it needs to be.

There should be a way to make eclipse include the XML file as part of the war file for deployment. I don't know what it is -- I don't use eclipse.

Once the file is properly deployed, you can use ServletContext.getResourceAsStream() to get at it.
1
+Pie Number of slices to send: Send
P.S. You want to avoid getRealPath() as it will fail in some circumstances (war file is not expanded).
+Pie Number of slices to send: Send
Ok, then the file is accessed like this:

Subsequently, the input must be converted to a file, right?

Why makes an IDE deployment so much more difficult and how could it be done better?
1
+Pie Number of slices to send: Send
 

Daniel Zuckermann wrote:Subsequently, the input must be converted to a file, right?


Huh? If you've got an input stream you can just read it. Why the need for any "conversion"?

Why makes an IDE deployment so much more difficult and how could it be done better?


A bazillion settings, and restrictions that make it hard to mimic the real world.

Personally, I use an IDE (IntelliJ IDE) as an intelligent editor, but use Ant for building for deployment, and run a standalone Tomcat instance. Your mileage may vary.
1
+Pie Number of slices to send: Send
Daniel, maybe this example will give you an idea: http://www.kodejava.org/examples/140.html

Also, you can find more examples with a search for reading a file from a servlet

For non-trivial web applications, I use the Spring Framework because it not only encourages me to write loosely-coupled, well-tested components, but it also provides a lot of the plumbing code that helps with things like reading files. I'm a lazy programmer and I always try to find a way to write as little code as possible myself. There's a lot of good open-source software out there and you can save a lot of time and effort if you know where to look.
+Pie Number of slices to send: Send
Thanks, but I haven't yet understood how this works in detail.

My XML parser class uses a normal File object:


According to this http://docs.oracle.com/javase/1.4.2/docs/api/javax/xml/parsers/DocumentBuilder.html , I could directly pass an InputStream to the parser. In my case this would
be a FileInputStream, right?
1
+Pie Number of slices to send: Send
parse is overloaded to take a File so you can call it the way you are doing now. Your problem is that the file can't be found, right? You can use File.exists() to check if you have specified the correct path. The article I cited might give you clues as to what you need to pass for the path.
1
+Pie Number of slices to send: Send
getRealPath may return null. If the webapp was not deployed as an exploded WAR, there is no real path, because the resource whose real path you are requesting resides inside the WAR file, not as a distinct file in the filesystem with a distinct filesystem path. There are times when I really wonder what genius created getRealPath to begin with.

Even if you do have an exploded WAR, getRealPath is a bad choice. If the XML file is a constant, read-only resource that's an integral and permanent part of the WAR, you are better off using the request getResourceAsStream() method in most cases. If the XML file is variable and/or uploaded you should absolutely positively not store it in the WAR. First, because if the WAR is not exploded, the file write will fail. Secondly, because the WAR may be updated an unforseen times, causing the uploaded file(s) to be destroyed without notice. And finally, because it's not an operation that is blessed by the J2EE and JEE standards. Always upload to an external directory that's outside of both your WAR and outside of your webapp server.
+Pie Number of slices to send: Send
It works with request getResourceAsStream(), but do I have to call input.close() in the servlet's destroy() method or is it not so important to do that?

If I have an index.jsp that requests data from a servlet that parses the xml and generates the beans out of the xml data sets, but where should the xml be parsed? When the XML file is large enough, it could happen that a button is pressed, but the data isn't already there. In the jsp I could overwrite the jspInit() method, but I would like to avoid scriptlets.

My idea is to start the application with a servlet instead of an index.jsp. This servlet's init() method acquires all resources (xml parsing, bean object creation....) and then forwards the request to the index.jsp.
1
+Pie Number of slices to send: Send
You should always close inputstreams as soon as you are done using them. Waiting for them to be garbage-collected or leaving them hanging open just wastes resources and may hold annoying file locks as well.

I would normally put the XML parsing in a JavaBean and (usually) store the parsed DOM in/as another JavaBean. Such beans may be referenced from JSPs, servlets, or subsidiaries of JSPs and servlets.

If the XML is global to all users, you can store it as an application-scope object. In that case you would probably parse the XML text in a ContextListener at application startup.
+Pie Number of slices to send: Send
In my case, the bean objects are read-only and the same for all users. I have one singleton class that manages and stores the beans in a Vector. Upon request, a Vector element is copied and sent to the user.

How does it work with this ContextListener and where should it be called?

Right now, the application is started with an index.jsp. It contains some buttons to request the data. However, I am not sure if the index.jsp should be the starter page. The index.jsp directly communicates with the Controller. The Controller calls the singleton class and processes the requests (according to model2). Problem here: The Controller is first called when a button is clicked.


1
+Pie Number of slices to send: Send
Actually, the webapp is started when the server deploys it, which can be when you explicitly deploy, or at server startup if the application had been deployed previously. If you instantiate a ServletContextListener and specify it in the WEB-INF/web.xml file, the "start" method can then kick off the process of parsing and holding your XML data. I do not recommend using a singleton class, however. Just keep the data in session scope.

Just as a side note, if the ultimate intent is to provide XML output using this XML as a model, a simpler solution might be to use the XML directly as a jspx. If the XML is serving in a more complex capacity (such as a Jasper Reports template or FO PDF template), you might want to consider an XML-friendly framework such as Apache Cocoon.
+Pie Number of slices to send: Send
I've overwritten the contextInitialized() method, but the problem here is, that I don't have a ServletContext to get the XMl file and save it as InputStream.

Maybe have to subclass HttpServlet and implement the ServletContextListener in the same class like

?
1
+Pie Number of slices to send: Send
The ServletContext is in the ServletContextEvent that gets passed to the ServletContextListener contextInitialized and contextDestroyed methods.
+Pie Number of slices to send: Send
Thanks, that works :-) In the contextDestroyed() method I've closed the InputStream.

It would also be nice to display some kind of "splash screen" or at least a "please wait..." message while the ServletContextListener is doing his work. Is this possible?
1
+Pie Number of slices to send: Send
I'm very puzzled. Normally, I'd code a contextInitialized method that obtained the XML, parsed it into a DOM object, then stored that DOM object (Document) as an application-scope property, closing the inputstream immediately after parsing it. On no account would I leave it hanging open wasting resources until the contextDestroyed method was invoked at webapp shutdown.

No, you cannot display a splash screen. No HTTP server can produce output unless a client has made an explicit request for output via an HTTP request and even then the only allowable output is an HTTP Response outputstream, one - and only one - per request. Also, the contextInitialized method will be invoked before the webapp beings accepting requests. And finally, the output response is not an asynchronous data stream, so by the time a "splash screen" was accepted and displayable by a client, the waiting would already be over.
If you're gonna buy things, buy this thing and I get a fat kickback:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com


reply
reply
This thread has been viewed 9376 times.
Similar Threads
Faster alternative(s) to java.util.zip??
Reading / writing to a file
how can i locate the properties files within the ejb container?
FileNotFoundException with relative path
Ruthlessly smash the bug...but where is it?
More...

All times above are in ranch (not your local) time.
The current ranch time is
Mar 19, 2024 01:50:06.