How to retrieve web application root path in Java - java

I am coding my Spring MVC based web application (which was deployed with a war file) and trying to get the value of
String rootDir = request.getSession().getServletContext().getRealPath("/");
I am expecting to get
"C:\user\projects\MyApp"
but the actual value is
"C:\user\projects\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\MyApp\"
I tried to change Source Folder Output Location in Eclipse, but after that all my jsp files, web.xml and folder \WEB-INF are gone. How can I restore them?
The reason I am asking this is that I want my uploaded images to be saved in "MyApp\webapp\WEB-INF\resources\images\" folder.

Why are you expecting the path to be "C:\user\projects\MyApp"?
Your are running your application using Eclipse and Eclipse is deploying it to C:\user\projects\.metadata\.plugins\org.eclipse.wst.server.core and not running it from project source folder that is why you get "C:\user\projects\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\MyApp\" from getRealPath() call.
From ServletContext#getRealPath()
Gets the real path corresponding to the given virtual path. For
example, if path is equal to /index.html, this method will return the
absolute file path on the server's filesystem to which a request of
the form http://://index.html would be
mapped, where corresponds to the context path of this
ServletContext.
The real path returned will be in a form appropriate to the computer
and operating system on which the servlet container is running,
including the proper path separators.
Resources inside the /META-INF/resources directories of JAR files
bundled in the application's /WEB-INF/lib directory must be considered
only if the container has unpacked them from their containing JAR
file, in which case the path to the unpacked location must be
returned.
This method returns null if the servlet container is unable to
translate the given virtual path to a real path.

Related

Eclipse not using relative file path [duplicate]

In my web application I have to send email to set of predefined users like finance#xyz.example, so I wish to add that to a .properties file and access it when required. Is this a correct procedure, if so then where should I place this file? I am using Netbeans IDE which is having two separate folders for source and JSP files.
It's your choice. There are basically three ways in a Java web application archive (WAR):
1. Put it in classpath
So that you can load it by ClassLoader#getResourceAsStream() with a classpath-relative path:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);
Here foo.properties is supposed to be placed in one of the roots which are covered by the default classpath of a webapp, e.g. webapp's /WEB-INF/lib and /WEB-INF/classes, server's /lib, or JDK/JRE's /lib. If the propertiesfile is webapp-specific, best is to place it in /WEB-INF/classes. If you're developing a standard WAR project in an IDE, drop it in src folder (the project's source folder). If you're using a Maven project, drop it in /main/resources folder.
You can alternatively also put it somewhere outside the default classpath and add its path to the classpath of the appserver. In for example Tomcat you can configure it as shared.loader property of Tomcat/conf/catalina.properties.
If you have placed the foo.properties it in a Java package structure like com.example, then you need to load it as below
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
// ...
Note that this path of a context class loader should not start with a /. Only when you're using a "relative" class loader such as SomeClass.class.getClassLoader(), then you indeed need to start it with a /.
ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
// ...
However, the visibility of the properties file depends then on the class loader in question. It's only visible to the same class loader as the one which loaded the class. So, if the class is loaded by e.g. server common classloader instead of webapp classloader, and the properties file is inside webapp itself, then it's invisible. The context class loader is your safest bet so you can place the properties file "everywhere" in the classpath and/or you intend to be able to override a server-provided one from the webapp on.
2. Put it in webcontent
So that you can load it by ServletContext#getResourceAsStream() with a webcontent-relative path:
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...
Note that I have demonstrated to place the file in /WEB-INF folder, otherwise it would have been public accessible by any webbrowser. Also note that the ServletContext is in any HttpServlet class just accessible by the inherited GenericServlet#getServletContext() and in Filter by FilterConfig#getServletContext(). In case you're not in a servlet class, it's usually just injectable via #Inject.
3. Put it in local disk file system
So that you can load it the usual java.io way with an absolute local disk file system path:
InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...
Note the importance of using an absolute path. Relative local disk file system paths are an absolute no-go in a Java EE web application. See also the first "See also" link below.
Which to choose?
Just weigh the advantages/disadvantages in your own opinion of maintainability.
If the properties files are "static" and never needs to change during runtime, then you could keep them in the WAR.
If you prefer being able to edit properties files from outside the web application without the need to rebuild and redeploy the WAR every time, then put it in the classpath outside the project (if necessary add the directory to the classpath).
If you prefer being able to edit properties files programmatically from inside the web application using Properties#store() method, put it outside the web application. As the Properties#store() requires a Writer, you can't go around using a disk file system path. That path can in turn be passed to the web application as a VM argument or system property. As a precaution, never use getRealPath(). All changes in deploy folder will get lost on a redeploy for the simple reason that the changes are not reflected back in original WAR file.
See also:
getResourceAsStream() vs FileInputStream
Adding a directory to tomcat classpath
Accessing properties file in a JSF application programmatically
Word of warning: if you put config files in your WEB-INF/classes folder, and your IDE, say Eclipse, does a clean/rebuild, it will nuke your conf files unless they were in the Java source directory. BalusC's great answer alludes to that in option 1 but I wanted to add emphasis.
I learned the hard way that if you "copy" a web project in Eclipse, it does a clean/rebuild from any source folders. In my case I had added a "linked source dir" from our POJO java library, it would compile to the WEB-INF/classes folder. Doing a clean/rebuild in that project (not the web app project) caused the same problem.
I thought about putting my confs in the POJO src folder, but these confs are all for 3rd party libs (like Quartz or URLRewrite) that are in the WEB-INF/lib folder, so that didn't make sense. I plan to test putting it in the web projects "src" folder when i get around to it, but that folder is currently empty and having conf files in it seems inelegant.
So I vote for putting conf files in WEB-INF/commonConfFolder/filename.properties, next to the classes folder, which is Balus option 2.
Ex: In web.xml file the tag
<context-param>
<param-name>chatpropertyfile</param-name>
<!-- Name of the chat properties file. It contains the name and description of rooms.-->
<param-value>chat.properties</param-value>
</context-param>
And chat.properties you can declare your properties like this
For Ex :
Jsp = Discussion about JSP can be made here.
Java = Talk about java and related technologies like J2EE.
ASP = Discuss about Active Server Pages related technologies like VBScript and JScript etc.
Web_Designing = Any discussion related to HTML, JavaScript, DHTML etc.
StartUp = Startup chat room. Chatter is added to this after he logs in.
It just needs to be in the classpath (aka make sure it ends up under /WEB-INF/classes in the .war as part of the build).
You can you with your source folder so whenever you build, those files are automatically copied to the classes directory.
Instead of using properties file, use XML file.
If the data is too small, you can even use web.xml for accessing the properties.
Please note that any of these approach will require app server restart for changes to be reflected.
Assume your code is looking for the file say app.properties. Copy this file to any dir and add this dir to classpath, by creating a setenv.sh in the bin dir of tomcat.
In your setenv.sh of tomcat( if this file is not existing, create one , tomcat will load this setenv.sh file.
#!/bin/sh
CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"
You should not have your properties files in ./webapps//WEB-INF/classes/app.properties
Tomcat class loader will override the with the one from WEB-INF/classes/
A good read:
https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html

Tomcat 8 error: invalid character ':' in value part of property

I just started learning Java EE and came across this error when attempting to deploy a WAR file on my tomcat server.
This error happens every time I use the manager application to deploy a WAR. When I select the file located at C:\Users\julex_000\workspace\application\target\application-0.0.1-SNAPSHOT, Tomcat sets it's name as /C:Usersjulex_000workspaceapplicationtargetapplication-0.0.1-SNAPSHOT. It then creates a file called C in the Tomcat8.0\webapps folder and when I try to start the application it fails every time.
The invalid ':' seems to be the colon after C in the path C:\Users\...
I also get an IOException about this:
This error only occurs when using the manager application. When I copy and paste the WAR into the webapps directory it works just fine.
It is simply not allowed to have a : in the context path.
At the deployment you have to pass a valid context path.
For example if you are using the tomcat manager ui:
You have to set the field Context Path and the WAR or Directory URL (the lokal path on the application server where tomcat can find the war file; If you tomcat is not on your localhost you have to move the war file manually and use the path on the server).
If you are using the form with the upload field in the ui, there is no input field where you can pass the context path, but tomcat will use the filename of the war (not the complete path) as context path.
At last but not least if you are using the non-ui-api you can just send your war file with a http put request and pass the url parameter path. You can find more information about this in the Documentation.

How to create a file in webroot during runtime in java web project?

Hi i must create a XML file in the project using java dynamically and must read it using the base Path URL. i can read the File when i create it manually, but not able to create it dynamically. When i use File f1 = new File("test.XML"); it create the file in the tomcat's Bin folder. The file must be created in the Project while Running in both Tomcat and Jboss EAP 6.
You can get the real path of the web application using the servlet context:
new File( servletContext.getRealPath( "/text.XML" ) );
Note: if you're running tomcat/jboss on Linux, you'll probably have to give permission to write in the webapp folder though, which is most likely forbidden by default.
Quoting from Servlet API docs of ServletContext.getRealPath():
Returns a String containing the real path for a given virtual path.
For example, the path "/index.html" returns the absolute file path on
the server's filesystem would be served by a request for
"http://host/contextPath/index.html", where contextPath is the context
path of this ServletContext..

Servlet/Tomcat relative file path

Where to put files in a Tomcat Servlet application, such that they are relatively visible to the page??
More detail:
I am developing a servlet page while using an external library. That library depends massively on external loaded XML files (relative file paths). So I need to put these XML files in the running directory of the servlet.
Is there a way in Tomcat server, where files can be accessible relatively?
When a web application is deployed to Tomcat, the root of the web application ends up being $CATALINA_HOME/webapps/YOUR_WEB_APP/
As such, if using a servlet to access an XML file located on a path within the root of your web application, you can just use the following:
request.getServletContext().getResourceAsStream("PATH/TO/YOUR/XML_FILE.xml")
This will load the XML file as an InputStream. Of course, if you want access to the file itself, you can always use the getResource(String resource) method to obtain a URL, from which a File object can be obtained like so (alternative methods included):
File f;
try {
f = new File(url.toURI());
} catch(URISyntaxException e) {
f = new File(url.getPath());
}
EDIT: To make them relatively visible to a web browser, simply keep them out of the ./WEB-INF and ./META-INF directories.
If this library you are talking about is going to search for the file on the classpath (like Hibernate or Log4J would do), you will have to put your XML file in WEB-INF. However, I suggest you do not do this manually. You can put the file in a source directory of you application, which will make sure the file gets deployed on the right spot.
This is an old question. I'm working on Tomcat 9. I've been quite successful with taking the Tomcat installation directory as the base. (CATALINA_HOME) The relative path to a file in ROOT for example is then, "webapps/ROOT/someDir/fileName"
The place to complain about repeated answers is to deal with repeated questions.

How to read a directory in webapp folder of Maven web application

I'm working in maven web application. I need to read a directory(For ex: Files) in my webapp folder as follows,
Java.io.File file = new Java.io.File("path");
But I don't know how to specify the path of the directory here.
You shouldn't give local path addresses. Path should be a relative address, e.g. /files/images under your web archive (.war) folder.
To use relative paths properly, I suggest you to add your target folder to the resources definiton of POM.xml, check out these pages
http://www.mkyong.com/maven/how-to-change-maven-resources-folder-location/
http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
You can refer to resources folder easily with something like this:
this.class.getResource("Mydirectory/SubDirectory");
When in doubt how relatives paths work, it's always best to do something like that:
System.out.println(new File("/my/desired/directory").getAbsolutePath());
This will print out the path in which classpath will look for the files.
Assuming:
servlet container webapps dir is located in: /var/lib/tomcat6/webapps
your webapp is called my-webapp.war
You should see the following output: /var/lib/tomcat6/webapps/my-webapp/my/desired/directory
Another pointer: you have mentioned that you are looking for webapp directory. I hope you know that this directory will not end up in *.war - it's contents will.
War files are not always expanded when they are deployed to an app server, so it's possible that a relative path won't exist in a filesystem at all.
Best bets are to use getResource from the class loader, which will return things in the class path (the WEB-INF/lib directory, etc), or to use the getResource() method of ServletContext to find things in the web application itself.

Categories

Resources