What is the best procedure for storing configuration data?
I have several classes that require some configuration data that is only needed in their class.
Should I load all this data from a configuration file or should I hardcode it into the classes?
Many thanks in advance
To address your question:
Should I load all this data from a configuration file or should I hardcode it into the classes?
Basically if you hard code some value into the class, you don't intend to change that value in different environments. Each such a change would require re-compilation of the project.
For example if you have a constant for PI=3.14 it doesn't make sense to use different values for different environments.
Alternatively if you go with configuration files, the update of such a file that can be supplied with a deployment script is much easier.
An example of this can be a host/port of the database. Development might use one host, production might use another.
So you should decide what works for you best.
This is common for all types of applications (not only spring boot driven).
Now its true that in spring boot you can create a configuration file (properties or yaml) and place it into the artifact (by putting it into src/resources/ or src/resources/config).
For some situations its good enough, for others you might use another way of configuration.
I don't refer managing secrets here, this is a more advanced stuff, but in general you won't want to manage things like passwords neither in the source code (hard coded) nor in the configuration file.
Related
Background : I don't want to hardcode properties in a java constant file, coz every time I want to change to one of the property_value, I have to build and deploy the entire code again. I don't even want to keep them in application.yaml/application.properties file, coz my properties are huge in numbers(100s). So, I have decided to maintain properties in a properties table in oracle DB.
I can think of two approaches :
Read the property value as and when required by firing a sql query.
Load all/part of the properties at the time of starting application and have global point of access by caching them.
As I need few of the properties in the beginning itself, I want to go with approach number 2.
I wanted to go for singleton bean, but this requires me to know all of the keys(property_names) in the beginning itself, and makes the singleton look ugly having 100s of member variables. Here I was planning to fire query by using pre-construct function of spring bean. The main problem here is the bean requires to be changed every time I add/delete properties from the properties table.
Another approach I could think of was to go with a Map<String,String> as both the property_name and property_value columns of my table are of VARCHAR type. But the question is how can I get global point of access to this map ?
Any better approaches much appreciated!
Many thanks in advance
If you deploy your app on web server you can take advantage of it. Many of web server supports changing configuration on the fly (using web console) such as JBoss EAP.
The other idea is to build your own properties lib. Create a function which read the data. I'd prefer using NoSQL database than RDBMS because of lightweight, great performance and scale very well. I wouldn't use caching unless it persisted somewhere and good on availability.
I've heard about Spring Cloud Config to externalize configuration but i never deep dive into it.
Some of us uses Apache Commons Configuration that support properties reload. Take a look at this thread.
I am working on a spring MVC web application. There is some master data for example currency code INR which I require on jsp page to compare with data from form bean. So which should be the correct place to store master data. Should it be in property file or do I need to fetch it from database and store it in any of the scope ?
Any kind of help will be appreciated.
If you don't expect to change data often then the property file is a fine place as a start. It is the simplest in terms of development effort. But note that to change the data you will need to restart the application.
Also if the application is running on multiple machines then each machine will have separate properties file. So you will have to edit properties files on all machines.
The database is better if you want to expose functionality to update the configuration to end-users. Also, the database will act as a single source of truth, no matter how many application nodes you have.
By currency codes, do you mean data like https://www.iban.com/currency-codes.html ?
In that case, it is a small amount of data that does not change often.
So the properties file is ok. To inject properties as a map (unknown number of keys, unknown exact key values) you need to use #ConfigurationProperties as described in https://docs.spring.io/spring-boot/docs/1.2.3.RELEASE/reference/htmlsingle/#boot-features-external-config-loading-yaml
I would go for a database if it is used by your project for other purposes. Otherwise, I would go for the properties file.
As said in the comments, business data belong in the database, even if you change them every other year. Property files are a great place for technical properties, especially those that are required before you load the Spring context. Those might be database credentials, logging level etc.
Consider that if you start to load-balance your application on different hosts, you'd have multiple property files, too. Imagine you forgot to update the currencies in one of them, you're gonna screw up the consistency of your whole database, when each instance of your app calculate different prices.
You may consider using yml/properties files with Spring Cloud Config. It's simple enough to use and it will give you a way to update your properties in runtime, without redeploying or even restart. So don't forget to enable Spring Actuator endpoints and get familiar with #RefreshScope annotation.
I am going to start a new project using Spring framework. As I dont have much experience in Spring I need your help to sort out few confusions.
Lets look at use case
My application uses Spring integration framework. The core functionality of my app is,
I need to poll multiple directories from file system,
read the files(csv mostly),
process some operations on them and insert them to database.
Currently I have set up spring integration flow for it. Which has inbound-chaneell-adapter for polling and then file traverse through the channels and at the end inserted into database.
My concerns are
Number of directories application supposed to poll will be decided at runtime. Hence I need to create inbound-chanell-adapter at runtime (as one chanell adapter can poll only one directory at once) and cant define them statically in my spring context xml (As I dont know the how many I need).
Each directory has certain properties which should be applied to the file while processing.(While going through the integration flow)
So right now what I am doing is I am loading new ClassPathXmlApplicationContext("/applicationContext.xml"); for each directory. And cache the required properties in that newly created context. And use them at the time of processing (in <int:service-activator>).
Drawbacks of current design
Separate context is created for each directory.
Unnecessary beans are duplicated. (Database session factories and like)
So is there any way to design the application in such a way that context will not be duplicated. And still I can use properties of each directory throughout the integration flow at the same time???
Thanks in advance.
See the dynamic ftp sample and the links in its readme about creating child contexts when needed, containing new inbound components.
Also see my answer to a similar question for multiple IMAP mail adapters using Java configuration and then a follow-up question.
You can also use a message source advice to reconfigure the FileReadingMessageSource on each poll to look at different directories. See Smart polling.
I'm writing an application with Spring MVC which I'd like to be configurable with properties files. I looked into Spring's util namespace and found this:
<util:properties id="MyProperties" location="propertiesPath" />
with this, I can annotate my classes field simply with
#Value("myProperty")
and have the property simply injected. So, it's very simple to read your properties. But when you have to save them, it's not as intuitive.
I've stumbled upon quite a few questions on how to do it properly and I think this represents best what I want to say: Updating a properties file injected by Spring to include a last run timestamp.
My question is: why it's so difficult to save properties in Spring? Am I doing it the wrong way? At this point I am even wondering if saving properties this way is a good practice or if I should use a database.
From Oracle I can read:
The Properties class represents a persistent set of properties. The Properties can be saved to a stream or loaded from a stream.
But Spring seems to make easier only one of them. Please enlighten me.
Thank you.
Spring is largely involved in creating the static, unchanging, structure of your application, and not really involved in transaction processing or business-logic. Often it defines how transactions are to be processed, but it isn't usually involved in the processing itself. We often talk about the separation of the domain model and the architecture -- spring is about architecture.
Writing something out to a store of some kind, say properties to a disk file, is transactional logic (even if you don't need an explicit transaction to do it). It would be one of the end-user features of your system, not part of the architecture -- it would be a feature (even if the end user, in this case, is a sys-admin). Spring has little support for this type of behaviour -- just as it has little support for storing information regarding dynamic changes to the application context.
Using properties like this supposed it read-only. If you need some managing with it, you should better write you custom service with pure java properties handling http://www.mkyong.com/java/java-properties-file-examples/
normally I place my translations etc in properties - e.g. message_de.properties etc. I'm facing now a situation where I have to provide this data in a database. (Translations will be imported/edited in an other system)
Is there a common way/best practises to use a database table for messages in my webapp? One way I would thinking of was to build properties from the database but this seems not the right way to go.
A ResourceBundle doesn't need to be based on a properties file, you can write your own implementation and back them with JDBC or whatever tickles your fancy. The ResourceBundle javadoc page has an example on how to make a custom implementation.
To me it sounds like exporting the database to properties files would be the correct way to go. It's simple and I would assume the database does not change that often? The export can then be automated different ways.