I am using Eclipse to create a Dynamic Web Project. My eclipse is in
/home/pc/eclipse
and My project is in /home/pc/workspace/MyWebProj
Now I placed the files in the above Project Directory. When I want to read any File from my code, It always searches the files in /home/pc/eclipse folder instead of /home/pc/workspace/MyWebProj, thus I am hardcoding the file path for time being.
Is there any configuration setting in Eclipse I am missing?
Please Suggest.
Thank You,
Tara Singh
I think what you need to do is read the file from the location of the javax.servlet.ServletContext of the Web Application. If you use getContextPath() you should get the working directory of the Web Application rather than the Java VM.
You could also try loading any files using the getResource and getResourceAsStream methods from the same class.
I was a little rushed when I wrote this so I will provide a little more info.
The best approach is to use the getResourceAsStream method. this allows you to access files within your webapp.
To get a file foo.txt from the root directory of the web application and print it to the response, you could do the following.
public class TestServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
PrintWriter writer = response.getWriter();
// foo.txt is at the root directory of the web app
InputStream in = getServletContext().getResourceAsStream("/foo.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String text;
while ((text = reader.readLine()) != null) {
writer.println(text);
}
}
}
I'm not sure what these files are, or more specifically, what the most appropriate storage location would be, but traditionally the best method of IO in this case is via ClassLoading. You could create a source folder located at src/main/resources that would be included in the archive (jar, war, ear, etc.) assembly (i.e. these files would be included in the jar). You would then load these resources.
If a file is located directly in the package, it will also be included in the artifact assembly, and can be accessed by any class in the package's class loader, or by the default class loader with the package path (packages correspond to folders when an archive is built).
If you are using a maven assembly plugin, these resources files would be included automatically. If you're using something like Ant, you would probably need to include these files in a script step. Otherwise I think if you're simply building in Eclipse there's a wizard for including files.
Also, the likely reason for attempting to read files from the /home/pc/eclipse folder is because a system property like user.dir or user.home is being utitlized:
String filename = System.getProperty("user.dir") + System.getProperty("file.separator") + "file.txt";
don't know if it's what you are looking for, but you can set/change the "Working Directory" of each "Running configuration" pretty easily in Eclipse.
Go to the "Run Configurations" Dialog
Select your Project (or the specific running config)
Select the "Arguments" tab
In the lower part of the Window, you can now change the "Working Directory" of the running configuration.
Change it to /home/pc/workspace/MyWebProj and your App should work.
Although this might work, i suggest you should go through a SystemProperty variable. Just get the parent path of your file like this:
File myFile = new File(System.getProperty("com.myapp.myfile.property"));
Now you can reset / move the working dir and filename via the System Properties just by setting this keyword.
Hope it helps a bit ;)
Related
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
I have done a project with a simple Java Rest service and Ajax calls.
Unfortanely if i set the path to the json file as something general (fileName.json), it will not open my file.
If i set a complete path like C:\Users\Username\workspace\RestApplication\fileName.json, it works but when i will submit the project for review, it wont have the same path on my teachers computer.
The file currently resides in the main folder of the project. How can i make a general path that will work on whatever computer opens the project?
Thanks!
you should put the file you want to load in the classpath.
The class path is the path that the Java runtime environment searches for classes and other resource files.
Put your file inside your src or resources folder (I don't know your project structure)
and try to load it with:
InputStream is = TestResource.class.getResourceAsStream("/fileName.json");
or put the file under WEB-INF
#Context ServletContext servletContext;
InputStream is = servletContext.getResourceAsStream("/WEB-INF/fileName.json");
Although numerous different options you most likely want to refer to it on the classpath. See https://en.wikipedia.org/wiki/Classpath_(Java)
I have a problem, I want to list the files in "default" folder, this folder is in the resources folder :
-resources/languages/default/manyfiles
The second line throws a nullPointerException
InputStream in = getClass().getClassLoader().getResourceAsStream("languages/default/");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
It seems I can't do this with a folder but only with a file. The problem is I can't use File because this is inside a jar.
EDIT : here the content of the jar :
http://www.mediafire.com/view/05u5w20xupt1mo1/javapbfolder.bmp
There is no standard way to list the contents of a folder. The reason is that there concept of a file system behind the class resource loading, just names/location of a resource.
It depends what you want to do, how to work around this. Possible solutions come to my mind:
Retrieve the URL from one resource in the directory. Extract the JAR file from the URL and open the JAR via the ZipFile class. This is "hacky" and may or may not work, depending on the platform you run and security settings.
Generate an index file when you pack the JAR that contains the list of the resources.
Put in a JAR into the resource, that you then open via ZipFile.
Scenario is the following:
Developing a jsp application with jdeveloper
Deploying to Oracle Weblogic
All files are in the same project
Source files are inside packages that are inside the src folder
Inside the Resources folder are two files: menu.json and TestWS.properties
So, I made a java class that should read menu.json and return a menu (in html) based on its structure.
When, inside the class, I do this
InputStream i =
Thread.currentThread().getContextClassLoader().
getResourceAsStream("Resources/menu.json");
BufferedReader r = new BufferedReader(new InputStreamReader(i));
The InputStreamReader constructor throws a NullPointerException, I suppose because it can't find the file.
Funny thing is, if I try to load TestWS.properties instead, it loads it just well.
I tried checking the project's properties, manually added both files under Project Source Path -> Resources, adding the .json extension to Compiler -> Copy file types to output directory, renamed, deleted, recreated, changed extension to the json file, deployed to WAR and loaded the project on another machine running weblogic, but to no avail.
Is there anything else I'm missing?
This is explained in this article.
In short, you have to change the compiler setting "Copy File Types to Output Directory" to include the extension of the resources you want to have available at runtime.
I'm working with a project that is setup using the standard Maven directory structure so I have a folder called "resources" and within this I have made a folder called "fonts" and then put a file in it. I need to pass in the full String file path (of a file that is located, within my project structure, at resources/fonts/somefont.ttf) to an object I am using, from a 3rd party library, as below, I have searched on this for a while but have become a bit confused as to the proper way to do this. I have tried as below but it isn't able to find it. I looked at using ResourceBundle but that seemed to involve making an actual File object when I just need the path to pass into a method like the one below (don't have the actual method call in front of me so just giving an example from my memory):
FontFactory.somemethod("resources/fonts/somefont.ttf");
I had thought there was a way, with a project with standard Maven directory structure to get a file from the resource folder without having to use the full relative path from the class / package. Any advice on this is greatly appreciated.
I don't want to use a hard-coded path since different developers who work on the project have different setups and I want to include this as part of the project so that they get it directly when they checkout the project source.
This is for a web application (Struts 1.3 app) and when I look into the exploded WAR file (which I am running the project off of through Tomcat), the file is at:
<Exploded war dir>/resources/fonts/somefont.ttf
Code:
import java.io.File;
import org.springframework.core.io.*;
public String getFontFilePath(String classpathRelativePath) {
Resource rsrc = new ClassPathResource(classpathRelativePath);
return rsrc.getFile().getAbsolutePath();
}
In your case, classpathRelativePath would be something like "/resources/fonts/somefont.ttf".
You can use the below mentioned to get the path of the file:
String fileName = "/filename.extension"; //use forward slash to recognize your file
String path = this.getClass().getResource(fileName).toString();
use/pass the path to your methods.
If your resources directory is in the root of your war, that means resources/fonts/somefont.ttf would be a "virtual path" where that file is available. You can get the "real path"--the absolute file system path--from the ServletContext. Note (in the docs) that this only works if the WAR is exploded. If your container runs the app from the war file without expanding it, this method won't work.
You can look up the answer to the question on similar lines which I had
Loading XML Files during Maven Test run
The answer given by BobG should work. Though you need to keep in mind that path for the resource file is relative to path of the current class. Both resources and java source files are in classpath