I am trying to use a properties file to store my DB connection details. It worked when I created a Java application and gave the file name as it is since I placed the properties file in the project root folder.
However, I get a FileNotFoundException when I try this in my Web application. I created a res directory under the project node to hold the properties file. I then gave the path as "res/db.properties" but I get the exception. I also tried placing this file under the configuration files directory but still got the same exception.
Here is my code -
import java.io.FileInputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Properties;
/**
*
* #author aj
*/
public class getConfigValues {
public String[] getPropValues() {
String[] props = new String[4];
try {
Properties prop = new Properties();
String propFileName = "res/db.properties";
InputStream input = null;
input = new FileInputStream(propFileName);
prop.load(input);
props[0] = prop.getProperty("dbURL");
props[1] = prop.getProperty("driverClass");
props[2] = prop.getProperty("user");
props[3] = prop.getProperty("password");
return props;
} catch (FileNotFoundException ip) {
props[0] = "not found";
return props;
} catch (IOException i) {
props[0] = "IO";
return props;
}
}
}
What am I doing wrong here?
As a web application you have no way of predicting the current working directory, so using a relative path will always be problematical;
Depending upon how you web application is packaged, your property file may not even be a file system object. It may well be a resource buried in a .war file.
One reliable way for you to access this file is to build it into your web app's WEB-INF directory. You can then access it using javax.servlet.ServletContext.getResourceAsStream("WEB-INF/res/db.properties").
Alternatively, you could build it into the WEB-INF/classes directory and load it using java.lang.ClassLoader.getResourceAsStream("/res/db.properties").
Most likely the current directory is different when you run it as a web app... There is a System property that will tell you what the current directory is. Or you can use Class.getResource to use your classpath to find the res directory
Your main mistake is trying to load a resource with file-related classes. Property files are resources to the application and thus should be placed relatively to this application.
"Relatively" means "in the class path".
In a standalone application, simply assure to mention the directory of those resources as part of the class path. In a web application, the directory WEB-INF/classes is already part of the application's class path.
Now comes the second part of the answer: How to load such resources? Simply: With a ClassLoader. Its responsibility is not only to load classes but also to load resources (such as property files).
Go with that (exception handling omitted):
ClassLoader loader = Thread.currentThread().getContextClassLoader();
URL resourceUrl = loader.getResource("res/db.properties");
Properties properties = new Properties();
try(InputStream input = resourceUrl.openStream()) {
properties.load(input);
}
String[] result = new String[4];
...
return result;
Related
A lot has been discussed already here about getting a resource.
If there is already a solution - please point me to it because I couldn't find.
I have a program which uses several jars.
To one of the jars I added a properties file under main/resources folder.
I've added the following method to the jar project in order to to read it:
public void loadAppPropertiesFile() {
try {
Properties prop = new Properties();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourcePath = this.getClass().getClassLoader().getResource("").getPath();
InputStream stream = loader.getResourceAsStream(resourcePath + "\\entities.properties");
prop.load(stream);
String default_ssl = prop.getProperty("default_ssl");
}catch (Exception e){
}
}
The problem (?) is that resourcePath gives me a path to the target\test-clasess but under the calling application directory although the loading code exists in the jar!
This the jar content:
The jar is added to the main project by maven dependency.
How can I overcome this state and read the jar resource file?
Thanks!
I would suggest using the classloader used to load the class, not the context classloader.
Then, you have two options to get at a resource at the root of the jar file:
Use Class.getResourceAsStream, passing in an absolute path (leading /)
Use ClassLoader.getResourceAsStream, passing in a relative path (just "entities.properties")
So either of:
InputStream stream = getClass().getResourceAsStream("/entities.properties");
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties");
Personally I'd use the first option as it's briefer and just as clear.
Can you try this:
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties")
My project structure looks like below. I do not want to include the config file as a resource, but instead read it at runtime so that we can simply change settings without having to recompile and deploy. my problem are two things
reading the file just isn't working despite various ways i have tried (see current implementation below i am trying)
When using gradle, do i needto tell it how to build/or deploy the file and where? I think that may be part of the problem..that the config file is not getting deployed when doing a gradle build or trying to debug in Eclipse.
My project structure:
myproj\
\src
\main
\config
\com\my_app1\
config.dev.properties
config.qa.properties
\java
\com\myapp1\
\model\
\service\
\util\
Config.java
\test
Config.java:
public Config(){
try {
String configPath = "/config.dev.properties"; //TODO: pass env in as parameter
System.out.println(configPath);
final File configFile = new File(configPath);
FileInputStream input = new FileInputStream(configFile);
Properties prop = new Properties()
prop.load(input);
String prop1 = prop.getProperty("PROP1");
System.out.println(prop1);
} catch (IOException ex) {
ex.printStackTrace();
}
}
Ans 1.
reading the file just isn't working despite various ways i have tried
(see current implementation below i am trying)
With the location of your config file you have depicted,
Change
String configPath = "/config.dev.properties";
to
String configPath = "src\main\config\com\my_app1\config.dev.properties";
However read the second answer first.
Ans 2:
When using gradle, do i needto tell it how to build/or deploy the file
and where? I think that may be part of the problem..that the config
file is not getting deployed when doing a gradle build or trying to
debug in Eclipse.
You have two choices:
Rename your config directory to resources. Gradle automatically builds the resources under "src/main/resources" directory.
Let Gradle know the additional directory to be considered as resources.
sourceSets {
main {
resources {
srcDirs = ["src\main\config\com\my_app1"]
includes = ["**/*.properties"]
}
}
}
reading the file just isn't working despite various ways i have tried (see current implementation below i am trying)
You need to clarify this statement. Are you trying to load properties from an existing file? Because the code you posted that load the Properties object is correct. So probably the error is in the file path.
Anyway, I'm just guessing what you are trying to do. You need to clarify your question. Is your application an executable jar like the example below? Are trying to load an external file that is outside the jar (In this case gradle can't help you)?
If you build a simple application like this as an executable jar
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class Main {
public static void main(String[]args) {
File configFile = new File("test.properties");
System.out.println("Reading config from = " + configFile.getAbsolutePath());
FileInputStream fis = null;
Properties properties = new Properties();
try {
fis = new FileInputStream(configFile);
properties.load(fis);
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e) {}
}
}
System.out.println("user = " + properties.getProperty("user"));
}
}
When you run the jar, the application will try to load properties from a file called test.properties that is located in the application working directory.
So if you have test.properties that looks like this
user=Flood2d
The output will be
Reading config from = C:\test.properties
user = Flood2d
And that's because the jar file and test.properties file is located in C:\ and I'm running it from there.
Some java applications load configuration from locations like %appdata% on Windows or /Library/Application on MacOS. This solution is used when an application has a configuration that can change (it can be changed by manually editing the file or by the application itself) so there's no need to recompile the application with the new configs.
Let me know if I have misunderstood something, so we can figure out what you are trying to ask us.
Your question is slightly vague but I get the feeling that you want the config files(s) to live "outside" of the jars.
I suggest you take a look at the application plugin. This will create a zip of your application and will also generate a start script to start it. I think you'll need to:
Customise the distZip task to add an extra folder for the config files
Customise the startScripts task to add the extra folder to the classpath of the start script
The solution for me to be able to read an external (non-resource) file was to create my config folder at the root of the application.
myproj/
/configs
Doing this allowed me to read the configs by using 'config/config.dev.properies'
I am not familiar with gradle,so I can only give some advices about your question 1.I think you can give a full path of you property file as a parameter of FileInputStream,then load it using prop.load.
FileInputStream input = new FileInputStream("src/main/.../config.dev.properties");
Properties prop = new Properties()
prop.load(input);
// ....your code
The directory structure of my application is as follows:-
My App
++++++ src
++++++++com
++++++++++readProp.java
++++++++resource
++++++++++message.properties
I am trying to read the file as follows:-
public Static final string FilePath="resource.message.properties"
Here the code to read the file. I tried using the following two techniques but to no use...
File accountPropertiesFile = new File(FacesContext.getCurrentInstance()
.getExternalContext().getRequestContextPath()
+ FilePath);
properties.load(externalContext.getResourceAsStream(FilePath));
But none yeild any sucess while reading through the Bean class. please help...
Your properties file is in the classpath. The java.io.File only understands the local disk file system structure. This is not going to work. You need to get it straight from the classpath by the classloader.
Here's a kickoff example:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("/resources/messages.properties");
if (input != null) {
Properties properties = new Properties();
try {
properties.load(input);
} finally {
input.close();
}
}
I don't know if this is your problem, but you should try using slashes instead of periods, since they're stored as actual folders in the filesystem.
I am trying to access a directory inside my jar file.
I want to go through every of the files inside the directory itself. I tried, for example, using the following:
URL imagesDirectoryURL=getClass().getClassLoader().getResource("Images");
if(imagesFolderURL!=null)
{
File imagesDirectory= new File(imagesDirectoryURL.getFile());
}
If I test this applet, it works well. But once I put the contents into the jar, it doesn't because of several reasons.
If I use this code, the URL always points outside the jar, so I have to put the Images directory there.
But if I use new File(imagesDirectoryURL.toURI());, it doesn't work inside the jar because I get the error URI not hierarchical. I am sure the directory exists inside the jar.
How am I supposed the get the contents of Images inside the jar?
Here is a solution which should work given that you use Java 7... The "trick" is to use the new file API. Oracle JDK provides a FileSystem implementation which can be used to peek into/modify ZIP files, and that include jars!
Preliminary: grab System.getProperty("java.class.path", "."), split against :; this will give you all entries in your defined classpath.
First, define a method to obtain a FileSystem out of a classpath entry:
private static final Map<String, ?> ENV = Collections.emptyMap();
//
private static FileSystem getFileSystem(final String entryName)
throws IOException
{
final String uri = entryName.endsWith(".jar") || entryName.endsWith(".zip"))
? "jar:file:" + entryName : "file:" + entryName;
return FileSystems.newFileSystem(URI.create(uri), ENV);
}
Then create a method to tell whether a path exists within a filesystem:
private static boolean pathExists(final FileSystem fs, final String needle)
{
final Path path = fs.getPath(needle);
return Files.exists(path);
}
Use it to locate your directory.
Once you have the correct FileSystem, use it to walk your directory using .getPath() as above and open a DirectoryStream using Files.newDirectoryStream().
And don't forget to .close() a FileSystem once you're done with it!
Here is a sample main() demonstrating how to read all the root entries of a jar:
public static void main(final String... args)
throws IOException
{
final Map<String, ?> env = Collections.emptyMap();
final String jarName = "/opt/sunjdk/1.6/current/jre/lib/plugin.jar";
final URI uri = URI.create("jar:file:" + jarName);
final FileSystem fs = FileSystems.newFileSystem(uri, env);
final Path dir = fs.getPath("/");
for (Path entry : Files.newDirectoryStream(dir))
System.out.println(entry);
}
Paths within Jars are paths, not actual directories as you can use them on a file system. To get all resources within a particular path of a Jar file:
Gain an URL pointing to the Jar.
Get an InputStream from the URL.
Construct a ZipInputStream from the InputStream.
Iterate each ZipEntry, looking for matches to the desired path.
..will I still be able to test my Applet when it's not inside that jar? Or will I have to program two ways to get my Images?
The ZipInputStream will not work with loose resources in directories on the file system. But then, I would strongly recommend using a build tool such as Ant to build (compile/jar/sign etc.) the applet. It might take an hour or so to write the build script & check it, but thereafter you can build the project by a few keystrokes and a couple of seconds.
It would be quite annoying if I always have to extract and sign my jar if I want to test my Aplet
I'm not sure what you mean there. Where does the 'extract' come into it? In case I was not clear, a sand-boxed applet can load resources this way, from any Jar that is mentioned in the archive attribute. Another thing you might do, is to separate the resource Jar(s) from the applet Jar. Resources typically change less than code, so your build might be able to take some shortcuts.
I think I really have to consider putting my Images into a seperate directory outside the jar.
If you mean on the server, there will be no practical way to get a listing of the image files short of help from the server. E.G. Some servers are insecurely set up to produce an HTML based 'file list' for any directory with no default file (such as an index.html).
I have only got one jar, in which my classes, images and sounds are.
OK - consider moving the sounds & images into a separate Jar. Or at the very least, put them in the Jar with 'no compression'. While Zip comression techniques work well with classes, they are less efficient at compressing (otherwise already compressed) media formats.
I have to sign it because I use the "Preferences" class to save user settings."
There are alternatives to the Preferences for applets, such as cookies. In the case of plug-in 2 architecture applet, you can launch the applet (still embedded in the browser) using Java Web Start. JWS offers the PersistenceService. Here is my small demo. of the PersistenceService.
Speaking of JWS, that brings me to: Are you absolutely certain this game would be better as an applet, rather than an app (e.g. using a JFrame) launched using JWS?
Applets will give you no end of stress, and JWS has offered the PersistenceService since it was introduced in Java 1.2.
You can use the PathMatchingResourcePatternResolver provided by Spring.
public class SpringResourceLoader {
public static void main(String[] args) throws IOException {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// Ant-style path matching
Resource[] resources = resolver.getResources("/Images/**");
for (Resource resource : resources) {
System.out.println("resource = " + resource);
InputStream is = resource.getInputStream();
BufferedImage img = ImageIO.read(is);
System.out.println("img.getHeight() = " + img.getHeight());
System.out.println("img.getWidth() = " + img.getWidth());
}
}
}
I didn't do anything fancy with the returned Resource but you get the picture.
Add this to your maven dependency (if using maven):
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
This will work directly from within Eclipse/NetBeans/IntelliJ and in the jar that's deployed.
Running from within IntelliJ gives me the following output:
resource = file [C:\Users\maba\Development\stackoverflow\Q12016222\target\classes\pictures\BMW-R1100S-2004-03.jpg]
img.getHeight() = 768
img.getWidth() = 1024
Running from command line with executable jar gives me the following output:
C:\Users\maba\Development\stackoverflow\Q12016222\target>java -jar Q12016222-1.0-SNAPSHOT.jar
resource = class path resource [pictures/BMW-R1100S-2004-03.jpg]
img.getHeight() = 768
img.getWidth() = 1024
I think you can directly access resources in ZIP/JAR file
Please see Tutorial its giving solution to your question
How to extract Java resources from JAR and zip archives
Hopes that helps
If I understand your problem you want to check the directory inside the jar and check all the files inside that directory.You can do something like:
JarInputStream jar = new JarInputStream(new FileInputStream("D:\\x.jar"));
JarEntry jarEntry ;
while(true)
{
jarEntry = jar.getNextJarEntry();
if(jarEntry != null)
{
if(jarEntry.isDirectory() == false)
{
String str = jarEntry.getName();
if(str.startsWith("weblogic/xml/saaj"))
{
anything which comes here are inside weblogic\xml\saaj directory
}
}
}
}
What you are looking for here might be the JarEntry list of the Jar... I had done some similar work during grad school... You can get the modified class here (http://code.google.com/p/marcellodesales-cs-research/source/browse/trunk/grad-ste-ufpe-brazil/ptf-add-on-dev/src/br/ufpe/cin/stp/global/filemanager/JarFileContentsLoader.java) Note that the URL contains an older Java class not using Generics...
This class returns a set of URLs with the protocol "jar:file:/" for a given token...
package com.collabnet.svnedge.discovery.client.browser.util;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class JarFileContentsLoader {
private JarFile jarFile;
public JarFileContentsLoader(String jarFilePath) throws IOException {
this.jarFile = new JarFile(jarFilePath);
}
/**
* #param existingPath an existing path string inside the jar.
* #return the set of URL's from inside the Jar (whose protocol is "jar:file:/"
*/
public Set<URL> getDirEntries(String existingPath) {
Set<URL> set = new HashSet<URL>();
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
String element = entries.nextElement().getName();
URL url = getClass().getClassLoader().getResource(element);
if (url.toString().contains("jar:file")
&& !element.contains(".class")
&& element.contains(existingPath)) {
set.add(url);
}
}
return set;
}
public static void main(String[] args) throws IOException {
JarFileContentsLoader jarFileContents = new JarFileContentsLoader(
"/u1/svnedge-discovery/client-browser/lib/jmdns.jar");
Set<URL> entries = jarFileContents.getDirEntries("impl");
Iterator<URL> a = entries.iterator();
while (a.hasNext()) {
URL element = a.next();
System.out.println(element);
}
}
}
The output would be:
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/constants/
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/tasks/state/
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/tasks/resolver/
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/
jar:file:/u1/svnedge-discovery/client-browser/lib/jmdns.jar!/javax/jmdns/impl/tasks/
May the following code sample can help you
Enumeration<URL> inputStream = BrowserFactory.class.getClassLoader().getResources(".");
System.out.println("INPUT STREAM ==> "+inputStream);
System.out.println(inputStream.hasMoreElements());
while (inputStream.hasMoreElements()) {
URL url = (URL) inputStream.nextElement();
System.out.println(url.getFile());
}
IF you really want to treat JAR files like directories, then please have a look at TrueZIP 7. Something like the following might be what you want:
URL url = ... // whatever
URI uri = url.toURI();
TFile file = new TFile(uri); // File-look-alike in TrueZIP 7
if (file.isDirectory) // true for regular directories AND JARs if the module truezip-driver-file is on the class path
for (TFile entry : file.listFiles()) // iterate top level directory
System.out.println(entry.getPath()); // or whatever
Regards,
Christian
I am new to servlet . I use the following code in servlet.then deployed to Jboss 4.1 . backup_database_configuration_location is location of properties file.But it can't be find. how I can specify directories in war file ?
Thanks all in advance
try {
backupDatabaseConfiguration = new Properties();
FileInputStream backupDatabaseConfigurationfile = new FileInputStream(backup_database_configuration_location));
backupDatabaseConfiguration.load(backupDatabaseConfigurationfile);
backupDatabaseConfigurationfile.close();
} catch (Exception e) {
log.error("Exception while loading backup databse configuration ", e);
throw new ServletException(e);
}
If it is placed in the webcontent, then use ServletContext#getResourceAsStream():
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/file.properties"));
The getServletContext() method is inherited from HttpServlet. Just call it as-is inside servlet.
If it is placed in the classpath, then use ClassLoader#getResourceAsStream():
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("file.properties");
The difference with Class#getResourceAsStream() is that you're not dependent on the classloader which loaded the class (which might be a different one than the thread is using, if the class is actually for example an utility class packaged in a JAR and the particular classloader might not have access to certain classpath paths).
Where is your properties file located? Is it directly somewhere in your hard drive, or packaged in a JAR file?
You can try to retrieve the file using the getResourceAsStream() method:
configuration = new Properties();
configuration.load(MyClass.class.getResourceAsStream(backup_database_configuration_location));
(or course, replace MyClass by your current class name)