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.
Related
Let's say I have a Spring Boot application running in AWS ECS. Let's further suppose that Spring Cloud Config Server is overkill, and we set all application properties via environment variables loaded via the current task definition.
E.g. in application.yml:
db:
url: ${DB_URL}
Let's also assume that the task definition pulls the necessary config values from AWS Parameter Store.
If I update the corresponding DB_URL value in AWS Parameter store, is there any reasonable way for the Spring application to see this value short of starting up a new container?
My hunch would be that, with the container already built, the values specified by the task definition were baked in to the container once it was created.
(I realize even if the updated value was visible that there's still the matter of properly updating the affected resource(s).)
Another thought might be to use AWS Secrets Manager as it seems to have the client-side caching library (https://github.com/aws/aws-secretsmanager-caching-java), but then all configuration values would have to be stored there instead of AWS Parameter Store.
I'm pretty sure I know the answer, but I wanted to make sure I'm not missing anything: Is there any other way to accomplish what's being asked besides the above? Or is the creation of a new container the only way (unless I want to switch to using, say, Spring Cloud Config Server)?
Thank you in advance!
Recreating the container is the only way to update the environment variables. This generally isn't an issue as ECS will spin up the new container, and start sending traffic to the new container, draining connections from the old container, so your application won't be down during this process.
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.
I've been tasked to have my (Java-GWT) web app determine the environment it's in based on the hostname of the server the app is running in. This would be easy enough to do if this check existed in the code (via InetAddress.getLocalHost().getHostName() although not preferred I know), but the request is that I add this configuration to the web.xml via the method mentioned in the title.
I don't know much about defining security realms or jaas domains but what I need is simple. I simply need to read in the hostname of the server and if the string patter prod exists, set a flag or value that the app code can access and decide against. Hopefully this makes sense.
If this strategy seems like a flawed one altogether, I'm open to suggestions on the best way to have my app determine which environment it's running in.
If I understand well, you want you application to know what environment it is running on. This has nothing to do with security (or at least I don't see it)
I would set the environment descriptive name as a property external to the application, for example as a custom JNDI resource, system property o environment property. Preferable the first in order to let the application declare its dependency, via a <env-entry>
https://docs.oracle.com/cd/E19857-01/820-1639/6nda10e5g/index.html#bhanr
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.
I'm working on a project in Java using the spring framework, hibernate and tomcat.
Background:
I have a form page which takes data, validates, processes it and ultimately persists the data using hibernate. In processing the data I do some special command (model)
manipulation prior to persisting using hibernate.
Problem:
For some reason my onSubmit method is being called twice, the first time through things
are processed properly. However the second time through they are not; and the incorrect
information is being persisted.
I've also noticed that on other pages which are simply pulling information from the data
base and displaying on screen; Double requests are happening there too.
Is there something misconfigured, am I not using spring properly..any help on this would
be great!
Additional Information:
The app is still being developed. In testing the app I'm running into this problem. I'm using the app as I would expect it to be used (single clicks,valid data,etc...)
If you are testing in IE, make note that in some versions of IE it sometimes submits two requests. What browsers are you testing the app in?
There is the javascript issue, if an on click handler is associated with submit button and calls submit() and does not return false to cancel the event bubble.
Could be as simple as users clicking on a link twice, re-submitting a form while the server is still processing the first request, or hitting refresh on a POST-ed page.
Are you doing anything on the server side to account for duplicate requests such as these from your users?
This is a very common problem faced by someone who is starting off. And not very sure about the application eco-system.
To deploy a spring app, we build the war file.
Then we put it inside 'webapps' folder of tomcat.
Then we run the tomcat instance using terminal (I am presuming a linux system).
Now, we set up env in that terminal.
The problem arises when we set up our environment for the spring application where there can be more than one war files to be deployed.
Then we must cater to the fact that the env must be exclusive to a specific war file.
To achieve this, what we can do is create exclusive env files for every war. (e.g. war_1.sh,war_2.sh,.....,war_n.sh) and so on.
Now we can source that particular env file for which we have to deploy its corresponding war. This way we can segregate the multiple wars (applications) and their environment.