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.
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?
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.
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?
Joined: May 14, 2012
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?
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.
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.
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.
An IDE is no substitute for an Intelligent Developer.
Joined: May 14, 2012
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.
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.
Joined: May 14, 2012
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.
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.
Joined: May 14, 2012
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
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.