How to load resource from an absolute path? - java

I am using ff4j like this:
FF4J ff4j = new FF4J("config.xml");
Internally, FF4J calls getClass().getClassLoader().getResourceAsStream("config.xml").
I want to be able to choose the config.xml location at deployment time (for example, /etc for linux).
How can I achieve that, without having to hardcode an absolute path? Is it possible to set the JVM / tomcat to look for the file in /etc for example? Or maybe there's another way to achieve what I want with FF4J?

As creator of FF4j I would add a couple of solutions.
Before 1.8.9
File configFile = new File("/tmp/ff4j.xml");
FileInputStream fis = new FileInputStream(configFile);
FF4j ff4j = new FF4j(fis);
Since 1.8.9
File configFile = new File("/tmp/ff4j.xml");
FileInputStream fis = new FileInputStream(configFile);
FF4j ff4j= new FF4j(new XmlParser(), fis);
As such you can now also import Yaml or properties files. (thinking about configMap in K8s world here). More samples here

Related

Deployed WAR can't access a file

I have a spring application, and i'm trying to access a json file with the following code :
try (FileReader reader = new FileReader("parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
I have put the parameter.json file in the project folder and I'm accesing the file data from an angular app through a rest api, and that works fine when I run the application on local machine, but when I deploy the war file on tomcat, my application can't load the file, should I put parameter.json file somewhere else on tomcat or what is the best solution for it.
Your question states you are attempting to access a file called parameter.json, while your code excerpt shows parameters.json. Perhaps that discrepancy indicates a typo in your source code?
If not, there are various ways to access a file from the classpath in Spring, with the first step for each being to ensure the file is in the project's src/main/resources directory.
You can then use one of the Spring utility classes ClassPathResource, ResourceLoader or ResourceUtils to get to the file. The easiest approach, though, may be to put your properties in a .properties file (default file name application.properties) and access the values using Spring's #Value annotation:
#Value("${some.value.in.the.file}")
private String myValue;
You can use other file names as well by utilizing #PropertySource:
#Configuration
#PropertySource(value = {"classpath:application.properties",
"classpath:other.properties"})
public class MyClass {
#Value("${some.value.in.the.file}")
private String myValue;
...
}
Make sure your parameters.josn filename is exactly same in the code.
Move you parameters.json file in the resources folder and then use the classpath with the filename.
try (FileReader reader = new FileReader("classpath:parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
Try to put the file under resources folder in your spring project. You should be able to access the file from that location.
FileReader is looking for a full-fledged file system like the one on your computer, but when your WAR is deployed, there just isn't one, so you have to use a different approach. You can grab your file directly from your src/main/resources folder like this
InputStream inputStream = getClass().getResourceAsStream("/parameters.json");

Java extended properties configuration

I am looking for implementation of properties configuration where properties are considered in the following order (or similar):
Command line arguments.
Java System properties(System.getProperties()).
OS environment variables.
Application properties outside of your packaged jar.
It means there would be application.properties file. This can be overwritten by OS environment variables and so on. Command line arguments overwrites all previous properties.
That is actually the way Springs PropertiesPlaceholderConfigurer is working, if you provide different PropertySources in the disired priority.
Unfortunatly it does only work with the Spring Framework.
you can do something like this
Properties properties = new Properties();
InputStream input = new FileInputStream(new File("settings.properties"));
properties.load(input);
String ipAddress = properties.getProperty("ip");
And save it when you exit for exemple
File f = new File("settings.properties");
OutputStream out = new FileOutputStream(f);
properties.setProperty("ip", ipAddress);
properties.store(out, "properties");

Load and Save Properties from file

In my spring project, I have in my classpath a file named database.properties with the following content:
jdbc.Classname=org.postgresql.Driver
jdbc.url=
jdbc.user=
jdbc.pass=
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=validate
I have a method in one of my service classes where I manually export the database schema to server through hibernate. The code for this method in this moment is this:
public void create_tables(String maquina, String usuario, String senha) {
Configuration config = new Configuration();
SchemaExport schema = new SchemaExport(config);
schema.create(true, true);
}
I want load the properties from file database.properties in my config variable, set up the values I pass to the method in this variable (url, user and pass), and save this new configuration in the same file.
Anyone can point the direction to do that?
does this do it?
Properties props = new Properties();
FileInputStream fis = new FileInputStream( "database.properties" );
props.load( fis );
fis.close();
props.setProperty("jdbc.url", {{urlvalue}} );
props.setProperty("jdbc.user", {{user value}} );
props.setProperty("jdbc.pass", {{pass value}} );
FileOutputStream fos = new FileOutputStream( "database.properties" );
props.store( fos );
fos.close();
I have in my classpath a file named database.properties
I want load the properties from file database.properties in my config variable, set up the values I pass to the method in this variable (url, user and pass), and save this new configuration in the same file.
This is at least difficult, and maybe impossible.
The "file" you are trying to update may not be a file at all. It might be a component of a larger JAR or ZIP file. It may be an in-memory or on-disk cache of something that was downloaded. It might (hypothetically) have been encrypted using a public/private key ... for which we don't have the "encrypt" key.
In addition to being difficult, it is a bad idea. Suppose that the your service is deployed as a WAR file, and that the properties file is delivered in the WAR. You modify the properties ... and so on. Then, for some reason you redeploy the WAR. This will overwrite your configuration.
If you want the configuration properties to be updatable, they should not be on the classpath. Put the file into a separate directory (outside of the webapp tree ...) and access it via a file pathname or file: URL.
I try remove the classpath:, but I face the error Caused by: java.io.FileNotFoundException: class path resource [database.properties] cannot be opened because it does not exist
It looks like you are using an (incorrect) relative path for the properties file.
Copy the file to (say) "/tmp/database.properties", change the annotation to
#PropertySource("/tmp/database.properties")
and see if that works. If it does, then you can figure out a more appropriate place to store the file. But as I said above, if you try to update a file in your webapp directory, there's a good chance it will get clobbered when you redeploy. So don't put it there.
Example load props from file.
We have test config file with filename = conf.props
Contains:
key0=value0
key1=value1
Next class load properties in the application:
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class LogProcessor {
public void start(String fileName ) throws IOException {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(fileName);
prop.load(fis);
System.out.println (prop.getProperty("key0"));
}
}
How to run:
public static void main(String[] args) {
try {
new LogProcessor().start();
} catch (IOException e) {
e.printStackTrace();
}
Return value0
\|/ 73

JAVA: FileInputStream and FileOutputStream

I have this strange thing with input and output streams, whitch I just can't understand.
I use inputstream to read properties file from resources like this:
Properties prop = new Properties();
InputStream in = getClass().getResourceAsStream( "/resources/SQL.properties" );
rop.load(in);
return prop;
It finds my file and reds it succesfully. I try to write modificated settings like this:
prop.store(new FileOutputStream( "/resources/SQL.properties" ), null);
And I getting strange error from storing:
java.io.FileNotFoundException: \resources\SQL.properties (The system cannot find the path specified)
So why path to properties are changed? How to fix this?
I am using Netbeans on Windows
The problem is that getResourceAsStream() is resolving the path you give it relative to the classpath, while new FileOutputStream() creates the file directly in the filesystem. They have different starting points for the path.
In general you cannot write back to the source location from which a resource was loaded, as it may not exist in the filesystem at all. It may be in a jar file, for instance, and the JVM will not update the jar file.
May be it works
try
{
java.net.URL url = this.getClass().getResource("/resources/SQL.properties");
java.io.FileInputStream pin = new java.io.FileInputStream(url.getFile());
java.util.Properties props = new java.util.Properties();
props.load(pin);
}
catch(Exception ex)
{
ex.printStackTrace();
}
and check the below url
getResourceAsStream() vs FileInputStream
Please see this question: How can I save a file to the class path
And this answer https://stackoverflow.com/a/4714719/239168
In summary: you can't always trivially save back a file your read from the classpath (e.g. a file in a
jar)
However if it was indeed just a file on the classpath, the above answer has a nice approach

How to reference a file in Eclipse that is not in src

I'm trying to get a resource for MyBatis. The tutorial states that I will need the following in my Connection Factory:
String resource = "org/mybatis/example/Configuration.xml";
Reader reader = Resources.getResourceAsReader(resource);
sqlMapper = new SqlSessionFactoryBuilder().build(reader);
My directory structure is:
src/
com/
utils/
MyBatisConnectionFactory.java
config/
Configuration.xml
I am having troubles referencing the configuration file. I tried "config/Configuration.xml", "Configuration.xml" and "/config/Configuration.xml".
Anyone have a good idea for what to do?
You can add your config directory as a source-folder (right-click > build path > use as source folder).
Thus your configuration files will go on the root of the classpath and will be accessible via getClass().getResourceAsStream("/Configuration.xml")
Open up the file via the classpath using getResourcesAsStream() rather than Resources.getResourceAsReader() For example:
InputStream is = getClass().getClassLoader().getResourceAsStream(
"src/com/utils/Configuration.xml");
byte[] data = new byte[is.available()];
is.read(data);
is.close();
String fileContents = new String(data);

Categories

Resources