aspose file tools*
The moose likes Servlets and the fly likes Relative path of an XML file? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Servlets
Bookmark "Relative path of an XML file?" Watch "Relative path of an XML file?" New topic
Author

Relative path of an XML file?

Daniel Zuckermann
Ranch Hand

Joined: May 14, 2012
Posts: 50
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?


Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

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?
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61010
    
  65

ItDoesntWorkIsUseless

Why didn't it work? What path did you end up with? How was it different from what you expected?


[Asking smart questions] [Bear's FrontMan] [About Bear] [Books by Bear]
Daniel Zuckermann
Ranch Hand

Joined: May 14, 2012
Posts: 50
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.
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61010
    
  65

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?
Daniel Zuckermann
Ranch Hand

Joined: May 14, 2012
Posts: 50
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?
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61010
    
  65

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.
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61010
    
  65

P.S. You want to avoid getRealPath() as it will fail in some circumstances (war file is not expanded).
Daniel Zuckermann
Ranch Hand

Joined: May 14, 2012
Posts: 50
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?
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61010
    
  65

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.
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4456
    
    6

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.


Junilu - [How to Ask Questions] [How to Answer Questions]
Daniel Zuckermann
Ranch Hand

Joined: May 14, 2012
Posts: 50
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?
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4456
    
    6

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.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16014
    
  20

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.


Customer surveys are for companies who didn't pay proper attention to begin with.
Daniel Zuckermann
Ranch Hand

Joined: May 14, 2012
Posts: 50
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.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16014
    
  20

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.
Daniel Zuckermann
Ranch Hand

Joined: May 14, 2012
Posts: 50
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.


Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16014
    
  20

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.
Daniel Zuckermann
Ranch Hand

Joined: May 14, 2012
Posts: 50
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

?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16014
    
  20

The ServletContext is in the ServletContextEvent that gets passed to the ServletContextListener contextInitialized and contextDestroyed methods.
Daniel Zuckermann
Ranch Hand

Joined: May 14, 2012
Posts: 50
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?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16014
    
  20

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.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Relative path of an XML file?