Loading Property File from Filesystem in Jboss Fuse / Karaf throws Nullpointer - java

I try to load a property file in Java running on JBossFuse/karaf.
The file is located at $[karaf.home]/etc/bean.properties
The Code is able to load properties inside the bundle fine, but now I try to exclude the properties from the project itself and the code throws a Nullpointer-Exception.
The Path is properly resolved on my development machine as
C:\Users\someone\devstudio\runtimes\jboss-fuse-6.3.0.redhat-135\etc\bean.properties
The property-File can be loaded in the blueprint-XML to configure beans, but to access the bean my code needs the CamelContext. As I have some static codeblocks that are accessed without an exchange/context/registry, I also wanted to be able to load the properties in Java.
Both the functions throw the NullPointerException and I guess, it is because the code runs in Fuse.
public static Properties getProperties(String location) {
Properties prop = new Properties();
InputStream input = null;
try {
input = PropertyLoader.class.getClassLoader().getResourceAsStream(location);
prop.load(input);
} catch (IOException ex) {
log.error("Error loading properties file from: " + location, ex);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
log.error(e);
}
}
}
return prop;
}
public static Properties getPropertiesFromFilesystem(String location) {
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream(location);
prop.load(input);
} catch (IOException ex) {
log.error("Error loading properties file from: " + location, ex);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
log.error(e);
}
}
}
return prop;
}
The Exception:
java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:434)[:1.8.0_91]
at java.util.Properties.load0(Properties.java:353)[:1.8.0_91]
at java.util.Properties.load(Properties.java:341)[:1.8.0_91]
at com.mycompany.util.PropertyLoader.getProperties(PropertyLoader.java:19)[319:camel-archetype-blueprint:0.0.14]
at com.mycompany.camel.blueprint.MyProcessor.process(MyProcessor.java:21)[319:camel-archetype-blueprint:0.0.14]
at org.apache.camel.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:63)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:468)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:192)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:76)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at java.util.TimerThread.mainLoop(Timer.java:555)[:1.8.0_91]
at java.util.TimerThread.run(Timer.java:505)[:1.8.0_91]
Any help would be highly appreciated.

Do not do that. You are looking for trouble.
Load properties the OSGi way (use .cfg as extension and a blueprint property-placeholder bean)
You have the added benefit of getting notified if the file changes (if you wish)
Inject them in a bean EVEN IF you are using only static methods.
Don't mix managed beans with unmanaged static code unless you know very well what you are doing.
If some "static" code requires properties means that it is stateful, and this class deserves to be instantiated to a bean.

Not sure why you are getting an NPE without a more complete example. If you need to use properties without a route, you should be using Camel's property placeholder facilities:
https://access.redhat.com/documentation/en-us/red_hat_jboss_fuse/6.3/html/apache_camel_development_guide/basicprinciples#BasicPrinciples-PropPlaceholders

Related

File not found java ini4j

I am trying to write something to a ini file using ini4j.
When i call the store() method it throws a FileNotFound exception even though it is in my project directory.
Maybe i did something wrong with my code?
Main:
public class Main {
public static Wini ini = null;
public static void main(String[] args) {
Config conf = new Config();
try {
conf.setMultiOption(true);
ini = new Wini();
ini.setConfig(conf);
ini.load(new File("apikeys.ini"));
} catch (InvalidFileFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
The file where i attempt to write and store the data:
if (KeyEndpoint.isValid(apikey)) {
Main.ini.put(apikey, Main.ini.get("Apikey"));
try {
Main.ini.store();
} catch (IOException e) {
channel.sendMessage("Invalid api key.").queue();
}
} else {
channel.sendMessage("API Key is invalid.").queue();
}
Any help is appreciated, I at least want to know what I am doing wrong.
Thanks!
It has to do with relative paths. Try changing the filename in Main for the absolute path, something like "/tmp/apikeys.ini", to check that your code works correctly. If that works, then you can now change it to either something like "../../directory/filename" or something relative to where you know you're executing your code from. Get familiar with your java path environment variables such as JAVA_HOME and all to get it to something more permanent and portable.

Unable to make getResourceAsStream() to load the .properties resource - using Netbeans IDE

First of, my sincere apologies for bringing up an oft repeated question in this forum; but I cannot figure out my mistake(s).
I have two .properties files that I am trying to load unsuccessfully. Here's the folder structure I have - unless there is a compelling reason otherwise or it is contrary to the best practice, I like to keep this structure:
As you notice my DAO code is under zencs.dbutils package and my .properties files are respectively under zencs.resources.properties.db* packages.
The reason I do it this way because eventually this will connect to and manage multiple data sources - my DAO code will evolve to handle them dynamically (not yet so). I want to set up all data source properties in one place
My Project properties are set as follows:
Now in my DAO class I have a method initProperties(), called by getConnection(), that is trying to reference these properties files through getResourceAsStream(). Please see below code that I tried:
public class DAO {
Connection conn = null;
public Properties properties = new Properties();
public Properties dbConnect = new Properties();
private void initProperties() {
InputStream inputDBdrivers = getClass().getResourceAsStream("snowflakeConnect.properties");
if (inputDBdrivers != null) {
try{
dbConnect.load(inputDBdrivers);
inputDBdrivers.close();
} catch(IOException ioex) {
System.err.println(ioex.getStackTrace().toString());
}
} else {
System.out.println("snowflakeConnect.properties file not found! Terminating Application normally...");
System.exit(0);
}
InputStream inputDBprops = getClass().getResourceAsStream("snowflake.properties");
if (inputDBprops != null) {
try{
properties.load(inputDBprops);
inputDBprops.close();
} catch(IOException ioex) {
System.err.println(ioex.getStackTrace().toString());
}
} else {
System.out.println("snowflake.properties file not found! Terminating Application normally...");
System.exit(0);
}
}
Connection getConnection() throws SQLException {
// build connection properties
initProperties();
try {
Class.forName(dbConnect.getProperty("driver"));
} catch (ClassNotFoundException cnfex) {
System.err.println("ERROR: getConnection() :: Snowflake Class not found: " + cnfex.getMessage());
}
return DriverManager.getConnection(dbConnect.getProperty("connectStr"), properties);
}
public DAO() {
try {
this.conn = getConnection();
} catch (SQLException sqlex) {
Logger.getLogger(DAO.class.getName()).log(Level.SEVERE, null, sqlex);
}
}
}
When I am executing it, the error says "snowflakeConnect.properties file not found! Terminating Application normally..."
My evaluation is that the code in the above form resolving the files to be in zencs/dbutils/ and the ClassLoader cannot find them there obviously.
I tried full absolute path (out of desperation though it expects relative); I tried relative path with "../resources/properties/{dbdrivers | dbutils}/filename.properties" with no success. With the relative path it is resolving to "zencs/dbutils/../resources/properties/dbdrivers/snowflakeConnect.properties" for ClassLoader...
Am I NOT setting the resources folder and everything underneath it correctly?
Obviously my comprehension of how it should resolve is flawed. Can you please help with what I might have not understood and how should I go about this issue?
Thanks a bunch!
You could try to use getResourceAsStream() including your package name like this:
InputStream inputDBdrivers = getClass().getResourceAsStream("/zencs/resources/properties/dbdrivers/snowflakeConnect.properties");
InputStream inputDBprops = getClass().getResourceAsStream("/zencs/resources/properties/dbutils/snowflake.properties");
The leading slash is usually the key part here. It could help to remove that as well but you said you've tried that already so I guess that's not what you're looking for.

Why isn't my properties file updated in my Web App project?

I am trying to read and write a properties file with all my server and database connections in my JSF web application project in eclipse. Am using log4j to write to console. My config.properties file is:
dbserver=localhost
dbname=mydatabase;instance=myinstance
dbuser=myuser
dbpassword=mypassword
I placed my config.properties file in webapp/WEB-INF/classes folder (this is the classpath right?). I have verified that it is reading the file correctly in this specific location because if I delete the file, it breaks.
In my managed bean, I have functions to read and write to the config.properties file.
public void getSettings() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("config.properties");
Properties properties = new Properties();
try {
properties.load(input);
this.server = properties.getProperty("dbserver");
this.db = properties.getProperty("dbname");
this.user = properties.getProperty("dbuser");
this.pass = properties.getProperty("dbpassword");
logger.info("Config file successfully loaded!");
} catch (IOException e) {
logger.error("Loading Database Settings Error with " + e);
} finally {
if (input != null) {
try {
input.close();
logger.info("Closing config file...");
} catch (IOException e) {
logger.error("Error closing config file with " + e);
}
}
}
}
public void saveSettings() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Properties props = new Properties();
OutputStream out = null;
try {
props.setProperty("dbserver", this.server);
props.setProperty("dbname", this.db);
props.setProperty("dbuser", this.user);
props.setProperty("dbpassword", this.pass);
URL url = classLoader.getResource("config.properties");
File file = null;
try {
file = new File(url.toURI().getPath());
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// File f = new File("config.properties");
out = new FileOutputStream(file);
props.store(out, "This is an optional header comment string");
logger.info("Config file successfully saved!");
} catch (IOException io) {
logger.error("Saving configuration properties failed error with : " + io.getMessage());
} finally {
if (out != null) {
try {
logger.info("Closing config file...");
out.close();
} catch (IOException e) {
logger.error("Failed closing configuration properties file error with : " + e);
}
}
}
}
I never had an issue reading from the properties file but had a hard time writing to the file. This issue seemed to have been solved by specifying
URL url = classLoader.getResource("config.properties");
Now, if I change the server name from "localhost" to "192.168.1.1", I can see that the new information persists even though I refresh the page or restart the server. HOWEVER... when I open the config.properties file, I still see
dbserver=localhost
when I am expecting to see
dbserver=192.168.1.1
The information seems to persist somewhere else even though the file still remains the same? How and where can I access the contents of my properties fie to see the changes that are being made to it?
Modifying the WAR file is a bad idea (for example, some web servers may notice the file modification an redeploy your app, there may be problems when the server explodes the war on deployment etc.)
I would suggest applying an alternative approach - some possibilities are:
Place the properties in a database table, so they can be easily modified
Use an external properties file for overriding your "Property.prop" file settings. You can pull this off for example as follows. Assume that the default property values are bundled in your WAR and the modified values are saved to some other path, which is defined using a system property - let say it's called CONFIG_LOCATION. Now after loading your properties from the bundle you read them also from this external "overrides.prop" file - this overrides your defaults from "Property.prop":
PropertiesConfiguration pc1=new PropertiesConfiguration(a);
try(
FileReader propReader = new FileReader(System.getenv().get("CONFIG_FILES") +"/overrides.prop"){ pc1.load(propReader);
}
When you need to save changes, you do that to "overrides.prop" - this will save all the properties, not only the changed ones, but that should have no negative effects.

Reading properties from an XML file using Input Stream?

Currently within my Java Application I have the following Class that I use in order to retrieve values from my properties file (application.properties):
public class MyProperties {
private static Properties defaultProps = new Properties();
static {
try {
java.io.InputStream in= MyProperties.class.getClassLoader().getResourceAsStream("application.properties");
defaultProps.load(in);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getProperty(String key) {
return defaultProps.getProperty(key);
}
}
An example of instantiating an int using the MyProperties class:
int maxNumberOfPeople = Integer.parseInt(MyProperties.getProperty("maximumPeople"));
I would like to change this class in order to read an XML properties file rather than e.g. application.Properties.
How can I do so, and still keep the ability to still instantiate values using the MyProperties class?
Read the javadoc for the Properties.loadFromXML(...) method.
Method summary:
Loads all of the properties represented by the XML document on the specified input stream into this properties table.
The Properties javadoc includes the DTD for the XML document (file).
It would be better to write your loader using a try-with-resources like this:
try (java.io.InputStream in = MyProperties.class.getClassLoader().
getResourceAsStream("application.properties")) {
// load properties
} catch (Exception e) {
e.printStackTrace();
}
Also, it is a bad idea to catch and squash exceptions like that.
Don't catch Exception.
If the properties failed to load, you most likely want the application to "bail out".
Finally, you probably shouldn't load the properties in a static initializer, because that leaves you with no clean way to deal with any exceptions that might arise.

Write to properties file on Wildfly which is loaded by ClassLoader

I am loading properties on an Wildfly application server like this:
public String getPropertyValue(String propertyName) throws IOException {
InputStream inputStream;
Properties properties = new Properties();
inputStream = getClass().getClassLoader().getResourceAsStream(propertyFileName);
if (inputStream != null) {
properties.load(inputStream);
} else {
throw new FileNotFoundException("property file '" + propertyFileName + "' not found in the classpath");
}
inputStream.close();
String property = properties.getProperty(propertyName);
LOG.debug("Property {} with value {} loaded.", propertyName, property);
return property;
}
Now I want to write to that very same file. How do I do that correctly? I tried around with new File(configurationFileName), but that creates a new File in a different directory, and I tried around with URL/URI of file from classloader, but that doesn't seem to work either. What is the correct way to do this?
Thx for help!
You can't and you shouldn't. I would use a database table to store and load properties. Or if it shall be a properties-file, then store it somewhere external via a file path, but not via the class path.
try (FileOutputStream out = new FileOutputStream(new File( getClass().getClassLoader().getResource(propertyName).toURI()))){
properties.store(out,"My Comments);
}
Raoul Duke is actually right, doing the properties via file raises a lot of problems. I will soon switch to DB for keeping those. In the mean time I did this: When I write properties, they are written to a newly created file. When I read properties, I load the "old" ones, and then create a new properties object with the old ones as defaults, in which I then load the new file.
private Properties loadProperties() throws IOException {
InputStream inputStream;
Properties defaultProperties = new Properties();
inputStream = getClass().getClassLoader().getResourceAsStream(defaultPropertyFileName);
if (inputStream != null) {
defaultProperties.load(inputStream);
} else {
throw new FileNotFoundException("Property file '" + defaultPropertyFileName + "' not found in the classpath");
}
inputStream.close();
Properties allProps = new Properties(defaultProperties);
try {
allProps.load(new FileInputStream(new File(updatedPropertyFileName)));
} catch (IOException ex) {
LOG.error("Error loading properties: {}", ex.toString());
return defaultProperties;
}
return allProps;
}
I marked his answer right, since I am technically not writing to the file I wanted to, plus this is only a workaround and his solution is way better and cleaner.

Categories

Resources