I have some static configurations that will not be changed for each environment, for example, the mapping between client names and their id. In this case, should I store them in a Spring yml property file or in a database, eg. mongoDB, so that they can be easily accessed via Java code?
From the one side, consider that when you are adding a database component, you are adding additional potential point of failure to your app. What will happen if DB will not be accessible, for any reason ? ( crashed, under maintenance, network issues ) ?
From the second side, it depends how exactly your implementation will be using files. For example, if you will be adding items in your mapping between clients/ids, will you need to restart/rebuild/redeploy your app? How many running instances of your app will you have?
So, there are no one exact answer for all cases
It better keep in spring yaml instead of storing in any Database. Because calling the IO operations little expensive . Keeping static code in yaml or properties file will faster to access.
Related
I want to initialize a data source in spring boot after the application context is initialized. There are several answers on the internet about how to setup multiple data sources, but each of them is done by somehow giving all the details in application properties before the application starts.
I found an article on baeldung about how to programmatically setup my data source, but this is not what I want.
https://www.baeldung.com/spring-boot-configure-data-source-programmatic
I will explain,
I am dealing with several databases, lets take as an example that I am the owner of several branches of a school. Lets call the schools - school1, school2, school3.... and so on till school100.
The datasource link for each school is somewhat like this
jdbc:postgres:schoolserver01:21000/school01
jdbc:postgres:schoolserver02:21000/school02
jdbc:postgres:schoolserver03:21000/school03
.
.
.
.
jdbc:postgres:schoolserver100:21000/school100
In simpler words, what I mean is that I can construct a string to match the data source URL based on some programming logic.
The problem that I am dealing with is, I don't want to give the data source URLs of all the schools in the application props, instead I want to initialize the data source as and when the requirement arises by building an instance of the datasource for the required school.
Please guide me if it is possible, if yes, then how?
Whatever you are trying to build is not practical and I doubt that you see a real world implementation on it. Spring boot when containerized should be disposable. One container should have only its dedicated database. I keep on writing more on this but it will help if you can read more on Microservice design.
We have a Spring web app which is behind nginx balancer. A need occurred to change some properties at runtime, preferrably without redeployment/restart.
However, a simple in-memory way like a controller which changes the value doesn't solve the problem because the balancer will send it to one specific server and others will have old property value.
This property change feature is a tool for support team and is not expected to be used often.
We came up with next ideas:
Controller + field in the database which holds actual value. However, in this case we will need to always query the DB for actual value.
Controller + curl script + list of actual servers, not the balancer. Will do the job, but very error-prone in future.
Forget the idea and just redeploy the app changing the properties file manually.
Maybe there's something else?
No code is available yet, it's more like a design question.
This is fairly straight forward with a simple Spring DAO approach. However, using MyBatis, is there a way to setup multiple potential datasources?
The best approach I can think of is to use an ArraList of a Bean each containing datasource.driverclass,datasource.url, datasource.username, datasource.password etc.
The values for the datasources are stored in individual properties files. There could be 1 or 10 of these property files (or more).
So for example, one application startup all the property files would be loaded one at a time into an ArrayList. Then, based on the NAME=value line from the property file, we would know which datasource to hit.
So http:localhost:8080/name=db1
... would access all the data from the datasource configured with the name "09". Each property file would contain:
name=db1
datasource.driverclass=jdbc:sqlserver
datasource.url=jdbc:sqlserver://localhost:1433;databaseName=someDBname
datasource.username=user1
datasource.password=pass1
So the identifier here is "name=db1".
Would the best approach from a MyBatis implementation utilise an ArrayList of Beans?
Here are some leads if you want to keep up with multiple DB:
Anyway, I would say datasources shall be managed in the server confiquration instead of in the App.
Then Mybatis main configuration file must be placed in a location added to the classpath, but outside of the app package, because every new datasource must be referenced there inside an environment element.
And for every user request or session (in case of a web app), the configuration will be parsed because SqlSessionFactoryBuilder.build(reader, environment=NAME); must be called to choose the environment (=> the DB).
I ended up using a hierarchical application.yml file detailing the multitenant connection values, based on a selected tenant code.
We are using the Spring integration FileTailingMessageProducer (Apache Commons) for remotely tailing files and sending messages to rabbitmq.
Obviously when the java process that contains the file tailer is restarted, the information which lines have already been processed is lost. We would like to be able to restart the process and continue tailing at last line we had previously processed.
I guess we will have to keep this state either in a file on the host or a small database. The information stored in this file or db will probably be a simple map mapping file ids (file names will not suffice, since files may be rotated) to line numbers:
file ids -> line number
I am thinking about subclassing the ApacheCommonsFileTailingMessageProducer.
The java process will need to continually update this file or db. Is there a method for updating this file when the JVM exits?
Has anyone done this before? Are there any recommendations on how to proceed?
Spring Integration has an an abstraction MetadataStore - it's a simple key/value abstraction so would be perfect for this use case.
There are several implementations. The PropertiesPersistingMetadataStore persists to a properties file and, by default, only persists on an ApplicationContext close() (destroy()).
It implements Flushable so it can be flush()ed more often.
The other implementations (Redis, MongoDB, Gemfire) don't need flushing because the data is written immediately.
A subclass would work, the file tailer is a simple bean and can be declared as a <bean/> - there's no other "magic" done by the XML parser.
But, if you'd be interested in contributing it to the framework, consider adding the code to the adapter directly. Ideally, it would go in the superclass (FileTailingMessageProducerSupport) but I don't think we will have the ability to look at the file creation timestamp in the OSDelegatingFileTailingMessageProducer because we just get the line data streamed to us.
In any case, please open a JIRA Issue for this feature.
I have a web-application running on Google AppEngine.
I have a single PRODUCTION environment, a STAGING env and multiple development & QA envs. There are many configuration parameters that should differ between PRODUCTION and other environments - such as API keys for services we integrate with (GoogleAnalytics for example). Some of those parameters are defined in code, other are defined in web.xml (inside init-param tag for Filters, for example), and others cases as well.
I know that there are a couple of approaches to do so:
Saving all parameters in the datastore (and possible caching them in each running instance / Memcached)
Deploying the applications with different system-properties / environment-variables in the web.xml
Other options...?
Anyway, I'm interested to hear your best-practices for resloving this issue.
My favorite approach is to store them all in datastore and having only one master record in it with all the different properties and making a good use of the memcache. By doing that you don't need to have different configuration files or polluting your code with different configuration settings. Instead you can deploy and change this values from an administrative form that you will have to create in order to update this master record.
Also if you are storing tokens and secret keys then you are aware of the fact that is definitely not a good idea to have them in the web.xml or anywhere else in the code, but rather having it per application on something more secure, like datastore.
Once you have that, then you can have one global function that will retrieve properties by name and if you want to get the Google Analytics ID from anywhere in your app you should use it by having something like this:
getProperty('googleAnalyticsID')
where this global getProperty() function will try to find this value with these steps:
Check if it exist in memcache and return
If not in memcache, update memcache from master entity from datastore and return
If not in datastore create an entity with a default values, update memcache and return
Of course there are different approaches on how to retrieve data from that Model but the idea is the same: Store in one record and use the memcache.
You must have separate app ids for your production/staging/qa envs. This must be hardcorded into your web.xml (or you have a script of some sort that updates your web.xml)
After that you can code in your settings based on appid. I assume there's a java equivalent to this:
https://developers.google.com/appengine/docs/python/appidentity/functions#get_application_id
You could put it in the datastore if they're settings that change dynamically, but if they are static to the environment, it doesn't make sense to keep fetching from datastore.