Apache Java Configuration API - configuration profiles (inheritance)? - java

When i was working with Zend Framework, I used to have .ini configuration files, where I could do this:
[production]
setting1 = abc
setting2 = def
[development : production]
setting1 = ghi
And when I turned on the development application profile then the setting1 had a value of ghi, whereas in the prdouction mode it was abc. Is is possible to define such inherited settings in Apache Commons Configuration?
I know that I can define multiple configuration files and create a CompositeConfiuration from them, but how to tell the application that it should include only specific files in different modes? I do not also have an idea how to set these application profiles yet but another setting called PROFILE should do the work for me.
If possible, I would not want to split the settings in multiple files.
I can't find any information about how this should be done in Java.

Apache Configuration reads the config options from a file into a memory data structure. Besides variable expansion, there is no further post processing by default. So your options are:
Put all options in a default config and then use individual "delta" configs that overwrite the defaults. Merge these individual files with CompositeConfiuration.
This design follows Java's inheritance model: Base type which you extend to overwrite some value and add new ones.
Create a post processor that takes the huge config and turns that into a new config with your preferred merging rules applied.
Create a helper object to look up values by key in the config. That would allow you do the merging at lookup time.

Related

Can Log4j2 be configured with .xml and .properties at the same time?

As above, can log4j2 be configured at the same time with .xml and .properties?
And if it can, what takes priority, when changing shared configuration?
This is the direct answer
Firstly: Why would you want to have multiple configuration files? Seems to me like you should try to collate all of your configuration into one file if at all possible.
The documentation for Log4J2 says that the automatic configuration will search first for the System property "log4j.configurationFile", which points to one configuration file on the file system, which is loaded based on the type of file.
If that isn’t found, it will search for:
.properties
.yml
.json
.xml
In that order.
This to me means that you can only use one.
This provides another approach
You can, however programmatically configure the logger, which can combine a configuration file with a different set of configurations.
If you wanted to combine the Configurator method with XML configuration, for example, then apparently you have to use the ConfigurationFactory, which is something I have never done before, though if you understand the layout of the Log4J2 it doesn't look too difficult - basically extending ConfigurationFactory, overriding methods to configure things, then giving the Configurator the factory.
Additional links:
Here is the programmatic configuration documentation
Here is a helpful Baeldung articl for programmatic configuration

Override spring-boot application configuration via external property file [duplicate]

This question already has answers here:
Spring Boot: Is it possible to use external application.properties files in arbitrary directories with a fat jar?
(12 answers)
Closed 3 years ago.
I want to override few configurations in my spring boot application during a restart via an external configuration file.
What I am using:
java -jar -Dspring.profiles.active=${ENV} my-application.jar
This loads my profile specific application property during application start. Let's assume I have an issue and I need to change the configuration in my application, I don't want to rebuild my application again with the changed property, what I want to achieve is that I provide an external property file which has the new value for the configuration and I restart my application.
I have tried suggestion mentioned here https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-application-property-files
Let's say I copy my jar to bin folder on my server and create a /config folder inside the bin folder which contains the override.properties file and then run the same command as stated above to restart my application.
It doesn't override the property mentioned in override.properties
I tried to provide spring.config.location as a command line argument but then I need to write all my properties in that file which is not what I need.
If you look at the top of Section 24 in the link you cite, you'll see a long list of places that Spring looks for property providers. Have you looked down that list? There are a number of options for providing external properties that override internal ones. Basically, anything higher on the list will override something lower on the list.
One option is to put JSON in the single environment variable SPRING_APPLICATION_JSON. This is what we do for unexpected overrides. We always define this variable in a separate file included by our main startup script, but it is usually empty. But at any time, we can go and add properties to it, and they will take priority and override any existing property values. We chose this option because it has a vey high priority. It is mostly only test code and settings that override these settings. The only other thing that does is properties put on the command line. Those, of course, can be changed without building a new binary.
There are other promising choices on that list, like #14. I believe there are ways of having external properties files that don't replace existing ones, but rather just override them, so that you don't have to redefine all of your existing properties there. I'd be surprised if there was no way to do that...have an external properties file that just overrode a few properties.
UPDATE: The "duplicate" cited in the question comments backs up what I'm saying here. It says very clearly that multiple properties files will override each other. No one file need provide all the properties. So it seems you're on the right track, and just have something wrong with your properties file configuration. Just keep in mind what I'm saying. It may be easier to use some other source than a properties file, like either the single environment variable SPRING_APPLICATION_JSON, or individual environment variables.

Is there a way to avoid configuring the same information multiple times?

My application utilizes many libraries that each require their own configurations.
For example, both Hibernate and Apache Shiro requires me to specify database connection details in the configuration files of each library. Is there any method of centralizing these values into a single file, XML or otherwise, that would make it a lot easier to manage?
In this situation, you can either
configure the libraries programatically, without configuration files, using a common framework. e.g. Spring.
generate the configuration files using templates for each configuration file and a shared set of properties.
There is no universal solution. Each library (typically) has its own way of doing configuration that isn't conducive for sharing with other libraries.
If you were using Spring DI, then there is considerable scope for sharing configuration via Spring XML wiring files ... provided that the library is configurable that way. (The latter means that you need to be able to inject the configuration information; e.g. as a Properties object.)
Another possibility is to use something else to generate your configuration files; e.g. Chef or Puppet ... or old fashioned macros.

Setting class properties in Java, Spring config Vs System Properties file

We can use both Spring config file OR a .properties file to store and retrieve some properties, like for a database connection. (db url, db password and etc)
We can also use Spring config file and a .properties file together, where we reference the property from a .property file (like in ant)
What would be the advantages or disadvantages for the following scenarios:
1 - Using only .properties file.
2 - Using only Spring config file.
3 - Using both together.
Would any of the scenarios be better when it comes to maintenance?
I need to choose between the three, and I would like to have a better judgement before I go with any of the option!
Thanks in advance!
- Ivar
Both together. Use a properties file that's externalizable from your project to configure Spring. Spring then configures your project. Mostly, you don't write code to read from properties files. Let Spring manage that and inject your objects with the appropriate values. Then you have appropriate dependency injection and the artifact you build isn't environment-specific.
Disadvantages:
How does your code know what file to load the properties from? Isn't that a property? It also violated dependency injection by having code go find a resource rather than passively accepting one.
Configuration is tightly coupled to your artifact and can't change between environments without rebuilding (BAD).
The way you seem to think of it, this combines the disadvantages of the other two, but if you do it the way I described, it eliminates those disadvantages, which is an advantage.

What is the best way to deal with environment specific configuration in java?

I have an application running in tomcat that has a bunch of configuration files that are different for each environment it runs in (dev, testing, and production). But not every line in a config file will be different between environments so there's invariably duplicated information that doesn't get updated if something changes.
Is there a good framework/library that collapses the separate files into one with environment specific blocks? Or some other way of dealing with this?
Assign reasonable default values for all properties in the properties files distributed within your .war file.
Assign environment-specific values for the appropriate properties in webapp context (e.g. conf/server.xml or conf/Catalina/localhost/yourapp.xml)
Have your application check the context first (for the environment-specific values), and fall back on the default values in the app's properties values if no override is found.
A Properties file is what I've always used. It's editable by hand as well as in in your software and the Properties object can read itself in and write itself out to the filesystem. Here's the javadoc page:
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html
If you use maven, you can use it's resource filtering abilities, along with profiles to generate a properties file for each environment you're deploying into.
As an added bonus, maven can also deploy your web app for you.
The duplication is not really a problem, having a central config file the the other files 'extend' is likely to casue more of a headache in the long term.
My advice is to use ant to load (copy and move) the appropriate file(s) into place and then launch the app (bundle into war?). Just have a different task for each environment. So you will have three config files (dev.config, test.config and production.config) which will be moved and overwrite the config in the /WEB-INF folder depending on the task that you are running.
I would suggest to have a separate config file for environment parameters alone if you want to avoid cluttering. Then you will have one more config file to manage. This is a trade off between number of config files vs complexity of each config file.

Categories