loading spring properties files from S3 bucket - spring

We have a application which is running on amazon EC2. we are planning to migrate it to elastic beanstalk environment. our application has two configuration files which stores some endpoints and few other control parameters. currently those are loaded as spring properties and injected to respective beans. we are thinking of putting them in to a S3 bucket and read them while loading the spring context. tries different approaches but still not luck.
1) what would be best advisable way to read the properties file with aws elastic beanstalk. we do not like to put them all as environment variables?
2) I tried creating a class extending
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
and tried by overriding processProperties method. but it seems annotation based property injection happens before calling this method. instance was created but the processPRoperties method was not called? any idea how this could be handled will be appreciated
EDIT
I have used a custom ApplicationContextInitializer registered in web.xml
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>com.xxx.PropertyInitializer</param-value>
</context-param>
in the initializer class injected the properties. seems it is working fine but then I'm facing another issue stated here.
Spring application context is converted to proxy after custom property injection

Related

Bind Spring datasource to JNDI

I have a spring boot based spring application that is deployed into an external tomcat instance.
The application creates few datasources. These datasources are added to entitymanager and transaction manager is setup accordingly.
However, recently we have integrated programmatically an ETL tool that works with JNDI datasources. The ask here is to bind the current spring datasources into the JNDI tree at startup.
I have tried to create an initial context post datasource bean creation and bind the datasources there, however, i do see a NoInitialContext exception being thrown.
How can i bind these spring datasources into the JNDI tree of the external tomcat? Appreciate the help!
Note: I cannot/am not allowed to edit the tomcat configuration as it is initialized from a PaaS template. So need to work on the approach of being able to bind to the JNDI tree from within the application.
AFAIK this is not possible. Take a look at the JEE spec:
The container must ensure that the application component instances have only read access to their naming context. The container must throw the javax.naming.OperationNotSupportedException from all the methods of the javax.naming.Context interface that modify the environment naming context and its subcontexts.
Jakarta EE Spec - Resources, Naming, and Injection
See this SO post has some interesting code examples if you want to play around.
IMHO you can achieve what you want by creating JNDI resources and passing these to the EntityManger/Spring. But that means that the configuration would exist outside of Spring completely. So this may not do what you want to do.

Spring Cloud Config and Spring Cloud Vault order of initialization

We are leveraging Spring Cloud Config and Spring Cloud Config Vault. We would like to know if there is a way to "bootstrap the bootstrap", ie we want spring cloud config server to be hit and then pull properties from that to leverage in our vault configuration. We looked at order, but it didn't appear to work, and I assume it is because of the post processing order, but I was hoping I might be missing something.
TL;DR
It doesn't work.
Explanation
What Spring Cloud does with its bootstrap context, is setting up an application context that contains a set of PropertySources initialized from Spring beans. The bootstrap context is used then as parent context for the actual context created by Spring Boot. A property lookup looks for properties in its own context and within the parent context.
Configuration properties are initialized very early in the startup process and they use properties from the current Environment. At the time ConfigurationProperties beans are initialized, the Environment does not yet contain any remote PropertySources.
The only option I see here (except creating a bootstrap-bootstrap-context) is using the Spring Cloud Config client within your main class and contribute Vault properties before any Spring context is built.
Probably you can, but it requires PropertySourceBootstrapConfiguration#initialize() method overriding. You can't disable bean PropertySourceBootstrapConfiguration, but you can disable it's initialize method by using applicationContext.getBeanFactory().getBean(PropertySourceBootstrapConfiguration.class).setPropertySourceLocators(new ArrayList<>()) in CustomPropertySourceBootstrapConfiguration (to avoid obsolete external property sources calls).
In your CustomPropertySourceBootstrapConfiguration#initialize method you can retrieve properties from config-server and then customize your vaultPropertySourceLocator by inserting generated in config-server secretId of token.
Don't forget to add your CustomPropertySourceBootstrapConfiguration to spring.factories.
So, it's not easy but it is possible.
We created the custom datasource using EnvironmentPostProcessor which will get called before autoconfigure beans
https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.application.customize-the-environment-or-application-context

How can I use a custom PropertyPlaceholderConfigurer in Grails

My project creates war files that get deployed in different tomcat instances. Instead of using properties files in all of these locations and remembering to update the property values in these files we extended Springs PropertyPlaceholderConfigurer to read properties from a Mongo. This works well for our java/spring based wars. The problem is trying to get our grails applications to use this bean. I have included the bean in the spring/resources.groovy(or xml) but grails does not honor the bean and it gets overridden (or overlooked) with it's own GrialsPlaceholderConfigurer. Is there a way to tell grails to use our own Configurer?
Seems that it's possible from grails 1.0. I never used it but adding the following code in your configuration should work:
beans {
addBeanFactoryPostProcessor(new PropertyPlaceholderConfigurer())
}
See also this test in the grails source code base.
I was able to solve this by just creating a bean. The original developer didn't understand Grails. Once I really looked at it I was able to the custom Configurer to work.

Is it possible to change properties of a bean (defined for a service) and reload it when the application is running?

I migrated a simple CRUD application developed in Java using OSGi to Grails using Spring. I converted all the REST resources to controllers and HTML pages to GSP views, keeping the rest of the Java code as such.
I have a DBService service, which helps connect to the DB and run queries on it, and a ProcessorService, which uses DBService to perform business operations.
I created beans for these services as follows:
beans = {
dbServiceBean(DBService, "test_db")
processorServiceBean(ProcessorService,ref("dbServiceBean"))
}
Everything is working fine with the above config.
Now, I want the application to be able to process multiple DBs (multi-tenant). I won’t know the name of the DB beforehand, however, so I can’t have a list of dbServiceBeans predefined.
Is it possible to rebuild/reload a bean with dynamically obtained values and reload the dependent beans as well when the application is running?
Grails already have the option to use multiple datasources.
You can change your DBService to get a connection from the datasources configured. If you just change it to a Groovy class and put it in grails-app/service you will get transactions and dependency injection by attribute name for free.

Having spring bean properties refreshed automatically from properties file

I'm using Spring 2.5.6. I have a bean whose properties are being assign from a property file via a PropertyPlaceholderConfigurer. I'm wondering whether its possible to have the property of the bean updated when the property file is modified. There would be for example some periodic process which checks the last modified date of the property file, and if it has changed, reload the bean.
I'm wondering if there is already something that satisfies my requirements. If not, what would be the best approach to solving this problem?
Thanks for your help.
Might also look into useing Spring's PropertyOverrideConfigurer. Could re-read the properties and re-apply it in some polling/schedular bean.
It does depend on how the actual configured beans use these properties. They might, for example, indirectly cache them somewhere themself.
If you want dynamic properties at runtime, perhaps another way to do it is JMX.
One way to do this is to embed a groovy console in your application. Here's some instructions. They were very simple to do, btw - took me very little time even though I'm not that familiar with groovy.
Once you do that you can simply go into the console and change values inside the live application on the fly.
You might try to use a custom scope for the bean that recreates beans on changes of the properties file. See my more extensive answer here.
Spring Cloud Config has facilities to change configuration properties at runtime via the Spring Cloud Bus and using a Cloud Config Server. The configuration or .properties or .yml files are "externalized" from the Spring app and instead retrieved from a Spring Cloud Config Server that the app connects to on startup. That Cloud Config Server retrieves the appropriate configuration .properties or .yml files from a GIT repo (there are other storage solutions, but GIT is the most common). You can then change configuration at runtime by changing the contents of the GIT repo's configuration files--The Cloud Config Server broadcasts the changes to any Client Spring applications via the Spring Cloud Bus, and those applications' configuration is updated without needing a restart of the app. You can find a working simple example here: https://github.com/ldojo/spring-cloud-config-examples

Resources