Spring beans based on properties - java

I am wondering if the below is possible in Spring
Read a property file using spring - this file has a list of jms queue names
Make spring loop on the above list and define beans that define Apache camel routes from that queue to a file
I could just create the routes using java code on the apache camel context, but wondering if it is possible through spring.

Reading a property file in a Spring XML wiring file is easy; e.g. using a PropertiesFactoryBean. However, the second part of the problem cannot (I believe) be solved without writing a significant amount of Java code.
I suggest that you read Section 3.8.3 of the Spring Reference that describes how to write your own FactoryBean classes. Another possibility is to create a custom Java configuration bean as described in Section 3.11. There may be other possibilities too.
Warning: none of this stuff is particularly straight-forward if you are coming at it for the first time.

Related

Separate properties file for multiple environments

I am trying to have separate property files for prod and dev environment.
I have two property files application-prod.properties, application-dev.properties placed in classpath:/config
I added VM option -Dspring.profiles.active=dev
According to what I understand from the documentation and many other references on the web, on accessing Spring Environment as environment.getProperty("") the property in "application-dev.properties" should be loaded. However, I am getting null and as it seems the property files are not read by Spring.
I also tried defining both the files in #PropertySource. Doing this, the file defined second is picked up and the corresponding property is returned. Spring is not choosing the file based on the active profile.
Am I missing something?
I also came across a issue raised through some SO questions, but I am not sure if it refers to the same problem.
Right, so documentation you are pointing to is from Spring Boot project. That is not the same as Spring Framework. If you are not using Spring Boot, -Dspring.profiles.active=dev wouldn't work.
You have two options:
Introduce Spring Boot to your project ans turn on auto-configuration (#SpringBootApplication or #EnableAutoConfiguration).
Use plain Spring Framework features like PropertyPlaceholderConfigurer, but it doesn't give you same flexibility as Spring Boot features and you will need to create some boilerplate code to handle various envs.

How to create a custom Spring PropertySource that depends on a Spring Bean

I'm attempting to use the spring-cloud stack for a project that would use Zuul. In my organization we have a custom configuration stack that is xml-based and does property composition and hierarchical overrides. Because of the way this configuration is handled, I've struggled to create a PropertySource for it.
My custom PropertySource must use my Config bean, but because the PropertySources are initialized during the bootstrapping of spring boot, the application context is not fully initialized yet and I can't get to my custom Bean that exposes our xml-based configuration system.
#ConfigurationProperties appears to be entirely biased toward .properties and .yaml files. The Config bean is initialized in an ApplicationContextInitializer. Is there a way to delay the resolution of the ConfigurationProperties within the various services so I can construct my custom property source using my Config bean after it is initialized?
I originally attempted (well before asking the question) to create a custom PropertySourceLocator in my config (as mentioned by Dave Syer and well documented in the link he gave) and register it with my own spring.factories (Again, demonstrated in the helpful link given by Spencer Gibb in the comment.) The problem is that my property source needs to be configured after some work that is done in an ApplicationContextInitializer and the property sources all seem to be resolved before that occurs (at least those wired in as a factory for org.springframework.cloud.bootstrap.BootstrapConfiguration). I guess I hinted at this by stating that I needed a particular bean in my PropertySource that I couldn't get from the ApplicationContext at the time.
Anyway, to get around that, I am now registering the property source in an PriorityOrdered ApplicationContextInitializer to take place after another one that initializes my config object. Something like: context.getEnvironment().getPropertySources().addFirst(myPropertySource);
This seems to get my property source into the environment at the correct time and allows me to perform customization of the context before hand as needed.
In Spring Cloud you would need to register some BootstrapConfiguration (per the user guide: http://projects.spring.io/spring-cloud/spring-cloud.html#customizing-bootstrap-property-sources) that has a PropertySourceLocator bean. It shouldn't be any harder than that.
P.S. #ConfigurationProperties is not biased toward .properties and .yaml files - it binds to the Environment which knows nothing about file formats.

How to modify properties resolved by Spring before their injection into beans

I need to provide support for external preperties decryption in Spring application. I planned to use a mechanism from spring-cloud-config, which is triggered after the Environment is ready and add decrypted properties with higher precedence. Unfortunately it heavily relies on Spring Boot bootstrap mechanism which emits ApplicationEnvironmentPreparedEvent. Looking into the Spring Framework code the environment and context creation is highly coupled and it would be rather hard to run my own code between that. The application I am working with is a large, multi module "standard" Spring MVC application and I would not like to convert it into Spring boot application right now.
Question:
How could I execute my code after the environment was created and before the context creation (to modify properties before they will be injected into "normal" beans) in Spring (not Spring Boot) application?
Alternative question:
Is there any other way to get control over properties being injected into beans (for modify values originally resolved by Spring)?
You can create a custom ApplicationContextInitializer which adds decryption or whatever to the PropertySources of your choice.
We do something similair in one of the application I currently develop. After loading some custom properties from files and databases we wrap all the available PropertySources in a EncryptablePropertySource because several properties are encrypted (We use the Jasypt library for that).
Use #Value("${propname}") annotation on a setter method, instead of using on the field.
You can write code to handle transform/validate the property in the setter method, and then assign to the field.
In the mean time I have found customizeContext method in ContextLoader which reads defined ApplicationContextInitializers. It is executed after the environment was created and before the context is reloaded, so decryption in an initializer should work (at least in the base case):
ConfigurableEnvironment env = wac.getEnvironment();
(...)
customizeContext(sc, wac);
wac.refresh();

Runtime loading of Controllers for Spring MVC and dynamically mapping requests/URLs

We are starting a new project using Spring MVC, and we would like to move away from annotation-driven request/url mapping. We wish to implement the following use case:
Use Case A
User enters a URL.
The request mapping handler retrieves a list of mappings (e.g. from the DB), and based on this dynamic list of mappings, it calls the relevant controller.
This is because we want to be able to do the following as well:
Use Case B
We want to load a new Controller (perhaps a new reports module) into the web app without having to redeploy or do a server restart.
We will map this new Controller to a URL and persist it somewhere (most likely the DB).
We would like the Controller to be registered in the Spring app context (managed by Spring).
We would then like to use this new Controller in the request mapping.
We've taken an initial look at the different ways we can implement this, but we are unsure of the best architecture/method to go about this route. A couple of questions:
For Use Case A, how do we implement this within the Spring MVC framework (or if it's possible)?
For Use Case B, is there a good framework or way to be able to do dynamically loading and registering of this for web applications? We've taken a cursory look at OSGI but it seems to be advisable for use in non-web applications.
For Use case A :
Instead of DB you can keep the url mappings in a property file and then use property place holder to initialize beans using xml configuration on context up. This way remaining inside the spring framework, you can avoid annotations.
For Use Case B :
Tomcat supports dynamic reloading of classes but that to of only non structural changes in class file. But this has memory leaks as well as it doesnt cleans up old instance of class loader rather it creates a new instance.
Its quite achievable using spring-mvc-router API.
Please check below link
url-action mapping & routing in Spring MVC 3.0
Here the URL can be configured to controller.method using .conf file, but this can be achievable using java configuration, and i haven't tried so far.
Also if xml configuration chosen, then check out the property 'autoReloadEnabled', but its not adviceable for production use.
Hope this helps!!!

Alternative to apache commons configuration for reading properties from database

I have just discovered that Apache commons-configuration can read properties from a DataSource, but it does not cache them. My application needs to read properties a lot of times and it is to slow to access the database each time.
I have a Camel application that sends all messages to routes that ends with my custom beans. These beans are created with scope prototype (I believe in OOP) and they will/need to read some properties and a data source (which reads from properties url/name/etc) that depends from the current user from a SQL db. Each message I receive creates a bean and so properties are reread.
Unfortunately, I am not free to choose where to read properties from because now there is another software (GUI) not written by me that is a User/properties manager that writes to db. So I need to read properties from it.
Can you suggest me an alternative?
You could use the Netflix Archaius project, which adds the caching behavior you are looking for as well as dynamic refresh capabilities. Archaius is built around Commons Configuration.
So, rather than subclassing the DatabaseConfiguration, you could use Archaius' DynamicConfiguration, which extends Commons' AbstractConfiguration. This class will cache whatever source you would like, and refresh the properties at an interval you specify using their poll scheduling class.
The only class you would have to implement is a PolledConfigurationSource which pulls data from the database and places it in a Map. Should be pretty simple.
https://github.com/Netflix/archaius/wiki/Users-Guide

Categories