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

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.

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

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.

Spring 3 #value annotation with maven profile properties

I have a bunch of properties defined in pom.xml for different profiles. I would like to use #value annotation to inject the property values. It is enough to get the values set at build time.
What kind of options I have with this #value annotation? Do I have to have a separate property file or can I utilize applicationContext.xml?
What I'd do is use the properties maven plugin to write the project properties to a file and then reference that file from Spring via the PropertyPlaceHolderConfigurer mechanism
The Maven filtering works as a simple textual substitution, it doesn't know anything about spring and annotations. Not sure which way is better for you, if you describe your problem (but not one of yours possible solutions), I could try to suggest more constructive solution.

multiple java servers and batch programs - XML configuration nightmare

I have an application that consists of approx. 20 java components.
About half of the components are servers and the other half batch programs.
Almost all of them talk directly to an oracle database (jdbc via some of our infrastructure code jars) the other couple of components talk to some of the servers which talk to the database.
Anyway, each component is configured with numerous XML configuration files.
These are becoming almost impossible to maintain.
Some of the configuration is specific to a component others are similar (database URLs, connectors etc)
What is worse is that the application is not installed in many environments - in fact only about 10 environments (qa, dev, production etc etc).
But the people who own these environments don't seem able to maintain the configs correctly.
In particular whenever there is an upgrade there is invariably configuration errors.
I have even started checking in some of the environments configurations into SVN along with the code.
I tried an xml schema validator at one point (it consisted of defining the valid XML in .xsd files and then throwing an error if the schema rules were breached but that didnt work)
I'm thinking I am missing something basic here - perhaps there is a tool to manage this or perhaps I should be storing the configuration in the database.
The application was largely designed by a colleague but I feel myself that it's overly configurable - in fact many of the config actually refers to classes - i.e. one can choose handlers and parsers etc - the XML config almost looks like code.
Any advice greatly appreciated
Peter
Substituting XML for code is usually a bad idea; things that are declarative are probably OK, but things that are procedural probably aren't.
If all that configuration was defined in Java code, a lot of the upgrade issues would turn into compilation issues. The compiler would pick them out for you, and you could correct them.
So you've got a multi-part problem. You need to rationalize your configuration information into a set of partitions (per-component, per-installation, global). You need to try to verify configuration information at compile-time, where possible. And you need to write validation for the loaded configurations, to sanity check them.
To the extent possible, shift configuration relatively static stuff into Guice (at least, it's what I prefer). A lot of things happen in a nice, type-safe way with it.
Consider running a WebDAV server for each instance of the app, and storing configuration into it. Each can hit a simple URL to pull the current versions of the configuration files.
Or, stand up a lightweight XML database like BaseX with its REST capability, then store and load your configuration information there. Use JSLP or something like it to have your components find the central configuration repository.
An additional advantage to using an XML DB is that you'll be able to do a lot of sanity checking and updating by querying across the set of all configuration files. For example, if a given instance of the application should have the same JDBC parameters in each configuration file, a simple xquery will tell you if that's true.
If you don't have the ability to modify the applications that are pulling the configuration file (the config file format is fixed), then consider writing a query servlets for the XML database that assemble the required configuration information, from nested blocks or templates. That will allow you to figure out what's common between the configuration files and dynamically generate parameterized versions of those blocks.
Sounds like the key here is making incremental improvements. Allow the old way to configure, but have the configuration load look for a central config source first.
I don't think that the syntax of the configuration files is at the heart of the problem: using Java properties files instead of XML would leave you with exactly the same issues. There may be an issue that the configuration information is too dispersed - it's hard to tell. The main issue seems to be that the whole thing is too fragile - the application is too dependent on manual configuration, and it seems that the configuration for each environment needs to be different. You should try to focus on reducing the number of configuration parameters that need to be set to make the system work (without necessarily reducing the options available for diagnostics etc for use when they are really needed.), on having intelligent defaults and self-configuration. Perhaps even invest in creating an installation wizard.
As you have some Oracle databases handy why not store your configuration in there?
Then you only need one or two configuration parameters to point to an Oracle database suitable for that environment and download the rest of the configuration from the database.
The contents of the configuration table should be pretty static for any given environment so there should be no need to amend anything except the jdbc connection when you migrate your software through its life cycle.

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