I have a java project named dbstuff which reads properties from db.properties with getClass().getResourceAsStream("/db.properties"). The values are things like connection strings, etc. This dbstuff is used in various projects most of them are web.
I now have a dropwizard project (maven) which uses dbstuff.jar as a dependency, this project is compiled as a fat jar as described here, at the moment the dbstuff only read values from db.properties if the file is present in /src/main/resources, and when the package is created the db.properties becomes embedded in the jar.
What i want to achieve is to make db.properties external, so that i can have various db.properties (one for each environment) but only one dropwizard jar, is this possible?
thank you
You could pass in the path to the external db.properties file at runtime via a system property, e.g.:
java -jar myjar.jar -DdbConfig=/path/to/db.properties
Then in your code within dbstuff.jar you can load the properties file:
final String path = System.getProperty("dbConfig");
final Properties properties = Properties.load(new FileInputStream(path));
Alternatively, as you've mentioned you are using Dropwizard, within your configuration file (the yaml file or whatever you are using) have a property which specifies where the external db.properties file is, load the properties during server initialisation and then pass them on to whatever requires it in dbstuff.jar.
You could then take this a step further, forget about the db.properties file and have an entire section in your Dropwizard config that specifies all the properties, e.g.:
db:
url: jdbc://....
user: dbuser
# etc...
And then pass on what the objects in the dbstuff.jar need. See Dropwizard's configuration documentation for more information on how to do this.
I think you can create a configuration class in DropWizard and then use it to return the correct configuration for each environment - https://dropwizard.readthedocs.org/en/latest/manual/hibernate.html.
As for your question, if you have multiple resources on the same path, even if on different jars, there is no guarantee of which one Java will be using. When you add a file named db.properties to /src/main/resources, it becomes the resource "db.properties", and is read as such:
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getResourceAsStream(java.lang.String)
Related
I am new to Springboot and I am having trouble with externalizing my properties files.
I have multiple ".properties" files that I have kept in a subdirectory "config/". I have removed context-placeholders from my project and have included the comma-separated properties files while executing the jar.
eg. java -jar myjar.jar --spring.config.location=file:////config/PROP1.properties, file:///config/PROP2.properties -debug
I have few questions
Why are the files in the config directory not being read even after explicitly mentioning where to look?
I have my own dependencies in the project that have same-named properties files packed in its jar. Is that creating any sort of problem when SpringBoot tries to read the files from the config folder while executing my project jar?
Update
Now I am keeping only a single properties file suppose ABC.properties outside the jar in the same directory . I am using the name "ABC" instead of "application". I am using the below command
java -Dserver.log.dir=/path/to/log/dir -jar myjar.jar --server.port=9090 --spring.config.name=ABC --prop1=val1
I have overriden a property in my external property file but I don't see the overriden value being used when I run the application. My new questions are
Is there anything wrong with the command-line?
I have the following line in xml bean configuration
<context:property-placeholder location="ABC.properties" />. Is this causing any sort of problems to detect and use the external properties?
If the above is true and I have to remove the line how will SpringBoot understand from where the property values are to be imported?
(Not related directly to the question) Is there a order that I need to follow while giving command line arguments?
Spring boot has explicit indicate how to write this external configuration. See doc ref here: https://docs.spring.io/spring-boot/docs/2.5.2/reference/htmlsingle/#features.external-config.files
Basically, you need to specify the location like this:
--spring.config.location=classpath:/somefolder/somefile.properties
--spring.config.location=file:./somefolder/somefile.properties
From your command line, it seems that you are missing one dash, and also using a wrong format of file schema.
Q1: Why are the files in the config directory not being read even after explicitly mentioning where to look?
A1: If your config folder is beside your jar file, your command should be like
java -jar myjar.jar --spring.config.location=file:./config/PROP1.properties
meanwhile, you can also use the full path to target your config file.
Q2: If I don't mention the properties files names explicitly as an argument then they won't be picked up even when they are in the config directory
A2: No. See this doc, Spring Boot will try to find config files from the four places:
A /config subdir of the current directory.
The current directory
A classpath /config package
The classpath root
If spring.config.location is not set, files in these folders named application.properties will be treated as valid config file. You can change the accepted file name by setting property spring.config.name.
Q3 About Config File Priority
A3 As described in the doc mentioned earlier, if same name properties appear in different config files, locations higher in the list override lower items.
Another tip, it will be better to remove config files inside the jar file, so you can get a full view of configuration just in one place (the externalized config folder);
I'm using the log4j2 library to manage the logging process.
I created a configuration file named log4j2.xml containing the Appenders and Loggers configurations. Then, I defined a Logger in each class
private static Logger my_logger = LogManager.getLogger(my_class);
I did not specify anywhere the name of the conf file, so I think that the library implicitly get and read it.
Now, I need to provide my application in the form of a jar file, so I need to make the config file available so that the user can modify and configure it.
In my case, I suggest to create a XXX folder at the level of the jar file, containing all the configuration files used by my app.
My question is how can I say to the app "get XXX/log4j2.xml" rather than the xml contained into the jar.
that config file must be located in the class path, if you want the app to read the configuration from any other location then you need to specify that using
PropertyConfigurator.configure("/myPath/log4j.properties");
Make any folder and put your property or xml file in that. In order to read the property file you can do something like this:
Properties objProperties = new Properties();
<your-class>.class.getClassLoader().getResource("folder/log4j.properties");
objProperties.load(isFile);
or, Also this:
InputStream ist = Thread.currentThread().getContextClassLoader().getResourceAsStream("folder/log4j.properties");
In case of java web application please use the link
I had a similar task a few weeks ago.
I solved it this way:
Store a template of your log4j2.xml inside your jar files resource folder
When running your application, check for a file named log4j2.xml in the jar files current directory
If there is one, use that to create your logger
If not, copy your template from within your jar to the jar files directory and then use that to create your logger.
Cheers
We are using a spring boot application, where properties are loaded from application.yml file instead of application.properties, located at src/main/resources/ which looks like below:
config:
host: localhost:8080
server: 123
And they are being pulled in a .java file like this
#ConfigurationProperties( prefix="config")
public class ConnectionImpl implements Connection{
#Value("${config.host}")
private Stringhost;
}
I am able to retrieve properties this way.
But we are trying to move the config properties from application.yml to a different .yml file which is located at a different location. (src/main/resources/env-config).
Now I am not able to retrieve properties same way, i.e, using #Value annotation. Is there any other annotation I need to add ?
From the documentation:
SpringApplication will load properties from application.properties (or application.yml) files in the following locations and add them to the Spring Environment:
A /config subdirectory of the current directory.
The current directory
A classpath /config package
The class path root
If you don’t like application.properties as the configuration file name you can switch to another by specifying a spring.config.name environment property. You can also refer to an explicit location using the spring.config.location environment property (comma-separated list of directory locations, or file paths).
The default search path classpath:,classpath:/config,file:,file:config/ is always used, irrespective of the value of spring.config.location. This search path is ordered from lowest to highest precedence (file:config/ wins). If you do specify your own locations, they take precedence over all of the default locations and use the same lowest to highest precedence ordering. In that way you can set up default values for your application in application.properties (or whatever other basename you choose with spring.config.name) and override it at runtime with a different file, keeping the defaults.
You need to supply a command line argument that tells SpringApplication where specifically to look. If everything in resources/ is added to the classpath root, then your command line would look like:
java -jar myproject.jar --Dspring.config.location=classpath:/env-config/service-config.yml
If you have a general application.yml under resources/, the properties in there will still be loaded but will take a lower precedence to the properties file specified on the command line.
Your question doesn't really say what you intend to do, but if you want to have a different configuration for different environments (e.g. development, test, production), there is a simple solution for that.
Place your config files in a file hierarchy like this inside your project:
src/
main/
resources/
application.yml
application-development.yml
application-test.yml
application-production.yml
When you now start your application with
java -jar mySpringApplication.jar -Dspring.profiles.active=development
the configuration from application.yml will be taken as a "base layer", overridden by the configuration in application-development.yml. By this, you can have "default" settings for all environments in application.yml and environment-specific configuration in the application-ENV.yml files. The same works for test and production.
No.
You'll be in a much better position if you avoid hard-coding file path like that within your code base. #ConfigurationProperties used to have a locations attribute but it's deprecated and already removed in 1.5.
In Spring Boot, you configure the Environment which is a single source of truth for your configuration. Rather than having settings buried in code, you should configure Spring Boot to read the files that you want. Read the documentation for spring.config.location. If you want to do this in a more transparent manner, perhaps EnvironmentPostProcessor is what you need
I am using Config. properties file for passing parameters to my methods Now i am loading file from
Properties Config= new Properties();
Config.load(new FileInputStream("C:\\Config. properties "));
As i don't want to keep it hard coded how can i set it with package level. or within application.
Thanks in Advance.
Make use of ResourceBundle Class. You just need to specify the properties file name. It will take the file from any path,provided the path should be in the classpath.
Example:
// abc.properties is the properties file,which is placed in the class path.You just need to
// specify its name and the properties file gets loaded.
ResourceBundle s=ResourceBundle.getBundle("abc");
s.getString("key"); //any key from properties file...
I was also just going to suggest that but you can also pass in the full path to the config file via a command line argument for example:
java YourApp -config C:\\config.properties
A properties file packaged with the application should not be loaded using the file system, but using the class loader. Indeed, the properties file, once the application is packaged, will be embedded inside a jar file, with the .class files.
If the config.properties file is in the package com.foo.bar, then you should load it using
InputStream in = SomeClass.class.getResourceAsStream("/com/foo/bar/config.properties");
Or with
InputStream in = SomeClass.class.getClassLoader().getResourceAsStream("com/foo/bar/config.properties");
You may also load it with a relative path. If SomeClass is also in the package com.foo.bar, then you may load it with.
InputStream in = SomeClass.class.getResourceAsStream("config.properties");
Note that Java variables should always start with a lowercase letter: config and not Config.
If it's just the path you're worried about then you can use a relative path:
Config.load(new FileInputStream("Config.properties"));
This will look in the current working directory. The upsdie: dead simple. The downside: it's not that robust. If you start your application from somewhere else without changing the working directory before, the file won't be found.
Put the config file in the classpath (where your .class files are), and access it using
getClass().getClassLoader().getResourceAsStream(_path_to_config_file);
There are two ways to get the path of the config files at runtime.
a) Getting it from database.
b) Getting it from custom properties of JVM configured at server level
Best process is "b" , you can change the properties of JVM at any time if path is changed and just restart the server.
How can I load the configuration information for hibernate dynamically from a config file. Netbeans currently hard codes that information into an xml file that is then compiled into the jar. I'm a newbie to Java/Netbeans coming from PHP land and am use to a central bootstrap that pulls from a .ini or something similar, but netbeans tends to hardcode this information upon generation of the models,etc in an xml file that is then compiled in the jar. I'm looking for conventional methods of setting up configuration for various client machines using various database configurations. I don't want to have to compile the app on each machine it must be installed on.
The configuration file is read using the Configuration class. By default, it uses the hibernate.cfg.xml file found in the classpath, but you can use the configure method taking a file as parameter, and store the config file on the file system rather than in the jar.
You can also put the static mapping, which never changes between configs, in a file inside the jar, and put the varying config inside an external file. Look at the javadoc for Configuration to know how to add resources and config files to the configuration.