Cannot load properties from jar - java

I have small app and I tested and packed to jar and am trying to run it but I have error.
Here is my project structure:
src
-kie.template
----- ServerMain.java ==> Class with main
-kie.template.util
---- PropUtils.java
---- server.properties
target
-kietemplate.jar
---- lib
In the main method, PropUtils class reads properties.
public class PropUtils {
private static final String PROPERTIES = "server.properties";
public static Properties load() {
Properties properties = new Properties();
InputStream is = null;
try {
properties.load(PropUtils.class.getResourceAsStream(PROPERTIES));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is!=null) try{is.close();}catch(IOException e){}
}
return properties;
}
}
}
When I run the ServerMain class directly, it works fine. But after I packed it to jar and run, it shows error:
java -cp lib -jar kietemplate.jar
Caused by: java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:418)
at java.util.Properties.load0(Properties.java:337)
at java.util.Properties.load(Properties.java:325)
at au.org.jeenee.kie.template.util.PropUtils.load(PropUtils.java:26)
The properties file is in the directory when I look into the jar file.
jar tf kietemplate.jar
Any help would be appreciated very much.
EDIT:
I changed the logic to read properties:
Properties properties = new Properties();
InputStream is = null;
try {
File file = new File("server.properties");
is = new FileInputStream(file);
properties.load(new InputStreamReader(is));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is!=null) try{is.close();}catch(IOException e){}
}
It requires the properties file in parent directory of the jar file.

Your code works fine on my computer, both from the JAR and the filesystem.
A possible cause for that behaviour is the filesystem being case insensitive, but the jar file being case sensitive. But we really can't tell from the source code alone.

Related

How to load external properties file with Java without rebuilding the Jar?

I use gradle which structures projects in maven style so I have the following
src/main/java/Hello.java and src/main/resources/test.properties
My Hello.java look like this
public class Hello {
public static void main(String[] args) {
Properties configProperties = new Properties();
ClassLoader classLoader = Hello.class.getClassLoader();
try {
configProperties.load(classLoader.getResourceAsStream("test.properties"));
System.out.println(configProperties.getProperty("first") + " " + configProperties.getProperty("last"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
This works fine. however I want to be able to point to .properties file outside of my project and I want to it to be flexible enough that I can point to any location without rebuilding the jar every time. Is there a way to this without using a File API and passing file path as an argument to the main method?
You can try this one, which will first try to load properties file from project home directory so that you don't have to rebuild jar, if not found then will load from classpath
public class Hello {
public static void main(String[] args) {
String configPath = "test.properties";
if (args.length > 0) {
configPath = args[0];
} else if (System.getenv("CONFIG_TEST") != null) {
configPath = System.getenv("CONFIG_TEST");
}
File file = new File(configPath);
try (InputStream input = file.exists() ? new FileInputStream(file) : Hello.class.getClassLoader().getResourceAsStream(configPath)) {
Properties configProperties = new Properties();
configProperties.load(input);
System.out.println(configProperties.getProperty("first") + " " + configProperties.getProperty("last"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
You can send the properties file path as argument or set the path to an environment variable name CONFIG_TEST
Archaius may be complete overkill for such a simple problem, but it is a great way to manage external properties. It is a library for handling configuration: hierarchies of configuration, configuration from property files, configuration from databases, configuration from user defined sources. It may seem complicated, but you will never have to worry about hand-rolling a half-broken solution to configuration again. The Getting Started page has a section on using a local file as the configuration source.

Why I cannot read properties file using getResourceAsStream from WEB-INF/classes in WildFly? [duplicate]

This question already has answers here:
How to read properties file in web application? [duplicate]
(3 answers)
Closed 7 years ago.
My PC's operating system is Windows 7 64-bit.
I created a very simple Dynamic Web Project app in Eclipse:
I have a app.properties file in WEB-INF/classes directory with these properties:
DefaultMaximumBatchSize=1000
DAOFactory=MSSQLSERVER
I have a class AppProperties which reads the above file into a Properties object at startup using getResourceAsStream:
public class AppProperties {
private static final Properties APP_PROPERTIES;
static {
InputStream inputStream = null;
APP_PROPERTIES = new Properties();
try {
inputStream = AppProperties.class.getResourceAsStream("/WEB-INF/classes/app.properties");
System.out.println("AppProperties: inputStream=" + inputStream);
if (inputStream != null) {
APP_PROPERTIES.load(inputStream);
}
} catch (Exception e) {
System.out.println("AppProperties: Exception occured; e=" + e);
}
}
public static String getValue(String propertyName) {
if (propertyName == null || propertyName.equalsIgnoreCase(""))
return null;
else
return APP_PROPERTIES.getProperty(propertyName);
}
}
I have a listener class AppContextListener:
public class AppContextListener implements ServletContextListener {
public AppContextListener() {
}
public void contextInitialized(ServletContextEvent arg0) {
String defaultMaxBatchSize = AppProperties.getValue("DefaultMaximumBatchSize");
System.out.println("AppContextListener: contextInitialized(ServletContextEvent): defaultMaxBatchSize=" + defaultMaxBatchSize);
}
public void contextDestroyed(ServletContextEvent arg0) {
}
}
I deployed the app to JBoss 4.2.3, run the JBoss 4.2.3 and I get this output in server.log:
AppProperties: inputStream=java.io.FileInputStream#1adde645
AppContextListener: contextInitialized(ServletContextEvent): defaultMaxBatchSize=1000
Perfect.
I then deployed the same app to WildFly 8.2.1, run the WildFly 8.2.1 and I get this output in server.log:
AppProperties: inputStream=null
AppContextListener: contextInitialized(ServletContextEvent): defaultMaxBatchSize=null
What happened? What is the correct way to read properties file in WildFly from WEB-INF/classes directory?
Class.getResourceAsStream() looks for a resource in all of the directories and jars that constitute the classpath of the application.
So, if you start a java program with
java -cp foo;bar.jar com.baz.Main
And you use SomeClass.class.getResourceAsStream("/blabla/app.properties"), The classloader will look for the app.properties file under foo/blabla, and in the blabla directory of bar.jar.
Now, in a webapp, what constitutes the classpath of the webapp is
the directory WEB-INF/classes
all the jar files under WEB-INF/lib
So, if you call
AppProperties.class.getResourceAsStream("/WEB-INF/classes/app.properties")
the classloader will look for app.properties in
/WEB-INF/classes/WEB-INF/classes
<all the jar files of WEB-INF/lib>/WEB-INF/classes
The conclusion is that, to load an app.properties file located in WEB-INF/classes, what you need is
AppProperties.class.getResourceAsStream("app.properties")
JBoss shouldn't have worked.
Class.getResourceAsStream retrieves the resource from the classpath and the webapp root folder is not in the classpath.
The WEB-INF/classes folder is. Use getResourceAsStream("/app.properties"), and remember to close the stream:
private static final Properties APP_PROPERTIES = new Properties();
static {
try (InputStream inputStream = AppProperties.class.getResourceAsStream("/app.properties")) {
System.out.println("AppProperties: inputStream=" + inputStream);
if (inputStream != null)
APP_PROPERTIES.load(inputStream);
} catch (Exception e) {
System.out.println("AppProperties: Exception occured; e=" + e);
}
}
Now, if app.properties is always next to AppProperties.class, instead of at the root, make the name unqualified (remove the /). This will work even when your class is in a package (and it is in a package, right?).
Try
InputStream inputStream =
this.getClass().getClassLoader().getResourceAsStream("/my.properties");`

URI is not hierarchical exception when running application from JAR

I've exported my Java console application to a Jar file, but when I run the jar and call code that parses in a JSON file I get a java.lang.IllegalArgumentException
Does anyone know why the exception is being thrown when I run the program as a JAR? The parsing works fine when the application is run from Eclipse.
This is the exact error that is output when I execute the jar file and call the code that parses the JSON file:
Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierar
chical
at java.io.File.<init>(Unknown Source)
at gmit.GameParser.parse(GameParser.java:44)
at gmit.Main.main(Main.java:28)
This is how the parsing is being done in my GameParser class:
public class GameParser {
private static final String GAME_FILE = "/resources/game.json";
private URL sourceURL = getClass().getResource(GAME_FILE);
private int locationId;
private List<Location> locations;
private List<Item> items;
private List<Character> characters;
public void parse() throws IOException, URISyntaxException {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
// read from file, convert it to Location class
Location loc = new Location();
loc = mapper.readValue(new File(sourceURL.toURI()), Location.class);
Item item = mapper.readValue(new File(sourceURL.toURI()), Item.class);
GameCharacter character = mapper.readValue(new File(sourceURL.toURI()), GameCharacter.class);
// display to console
System.out.println(loc.toString());
System.out.println(item.toString());
System.out.println(character.toString());
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is the folder structure of my project:
The call getClass().getResource(GAME_FILE); will return a URL relative to this class. If you are executing your program from a JAR file, it will return a URL pointing to a JAR file.
Files in java can only represent direct filesystem files, not the ones in zip/jar archives.
To fix it:
Try to use getClass().getResourceAsStream() and use that instead of Files or
extract the files into some directory and use File in the same way as you are trying now.
This problem happen when you have two files with the same name,i mean in your project you have folder whith name "Images" and in your desktop you have other folder his name "images" automatically JVM choose desktop folder ,so if you want to confirm try to print your URI.Use this example to show your URI before creating your file
try {
URL location = this.getClass().getResource("/WavFile");
System.out.println(location.toURI());
File file = new File(location.toURI());
if (!file.exists()) {
System.out.println(file.mkdirs());
System.out.println(file.getAbsoluteFile());
}else
{
System.out.println(file.getPath());
}
} catch (Exception e) {
e.printStackTrace();
}

Unable to load external files in java while running in terminal

I have created a executable jar package (called myjar.jar) which has a class for reading config file(called config_reader) .There is another class file outside myjar.jar which uses the config_reader. But the config file for config_reader is placed outside the myjar.jar ( in local filesystem) .Now when i try to execute the executable jar along with another file that uses it i get an error saying config file not found :
I tried to :
java -classpath config myclass.class
can Anyone help out on this ?
The code of config_reader is :
public class config_reader()
{
public static ArrayList<String> get_prop()
{
Properties prop = new Properties();
ArrayList<String> s= new ArrayList<String>();
try {
//load a properties file
prop.load(new FileInputStream("config"));
//get the property value and print it out
s.add(prop.getProperty("source_folder_dir"));
s.add(prop.getProperty("dest_folder_dir"));
s.add(prop.getProperty("file_type"));
s.add(prop.getProperty("username"));
s.add(prop.getProperty("userpwd"));
s.add(prop.getProperty("exclusion_list"));
} catch (IOException ex) {
ex.printStackTrace();
}
return s;
}
}
prop.load(new FileInputStream("config"));
Instead of just saying config use absolute path to the file. Infact it is better to do
File configFile = new File("absolute path to config file");
if(configFile.exists()){
//continue with your logic
}

Reading Properties file inside conf folder

I have a properties file which is located under conf folder. conf folder is under the project root directory. I am using the following code.
public class PropertiesTest {
public static void main(String[] args) {
InputStream inputStream = PropertiesTest.class
.getResourceAsStream("/conf/sampleprop.conf");
Properties prop = new Properties();
try {
prop.load(inputStream);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(prop.getProperty("TEST"));
}
}
But I get nullpointer exception.
I have tried using
InputStream inputStream = PropertiesTest.class
.getResourceAsStream("./conf/sampleprop.conf");
and
InputStream inputStream = PropertiesTest.class
.getResourceAsStream("conf/sampleprop.conf");
But all result in nullpointer exception.
Can anyone please help.
Thanks in advance
Try to recover your working directory first:
String workingDir = System.getProperty("user.dir");
System.out.println("Current working dir: " + workingDir);
and then is simple:
Properties propertiesFile = new Properties();
propertiesFile.load(new FileInputStream(workingDir+ "/yourFilePath"));
String first= propertiesFile.getProperty("myprop.first");
Regards, fabio
The getResourceAsStream() method tries to locate and load the resource using the ClassLoader of the class it is called on. Ideally it can locate the files only the class folders .. Rather you could use FileInputStream with relative path.
EDIT
if the conf folder is under src, then you still be able to access with getResourceAsStream()
InputStream inputStream = Test.class
.getResourceAsStream("../conf/sampleprop.conf");
the path would be relative to the class from you invoke getRes.. method.
If not
try {
FileInputStream fis = new FileInputStream("conf/sampleprop.conf");
Properties prop = new Properties();
prop.load(fis);
System.out.println(prop.getProperty("TEST"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
NOTE: this will only work if it is Stand alone application/in eclipse. This will not work if its web based (as the root will be Tomcat/bin, for eg)
I would suggest to copy the configuration file at designated place, then you can acess at ease. At certain extent 'System.getProperty("user.dir")' can be used if you are always copying the file 'tomcat` root or application root. But if the files to be used by external party, ideal to copy in a configurable folder (C:\appconf)
Your code works like a charm! But you might have to add the project root dir to your classpath.
If you work with Maven, place your configuration in src/main/resources/conf/sampleprop.conf
When invoking java directly add the project root dir with the java -classpath parameter. Something like:
java -classpath /my/classes/dir:/my/project/root/dir my.Main

Categories