How to load beans based on custom properties - spring

I have custom implementation of PropertySourcesPlaceholderConfigurer, which I'm using to load additional property sources and placing them into different position (one on the end, and one before systemProperties). So properties can be overridden on different level.
Based on some properties, I need to load set of beans. For that I'm implementing ImportBeanDefinitionRegistrar.
Unfortunately that ImportBeanDefinitionRegistrar is executed before PropertySourcesPlaceholderConfigurer.
I also tried to use #ConditionalOnProperty, with the same result. And with PropertySourceFactory which is executed on the early beginning, but at that point I can't position those additional property sources.
Is there a way to add additional PropertySource in custom order before ImportBeanDefinitionRegistrar, or on the early beginning of Spring lifecycle?
Here I have sandbox app to play with the concept.
In reality I have this as in house library for Spring and Spring Boot applications, to enable additional functionalities with properties.

You should implement EnvironmentPostProcessor and move all the logic for the property sources there. You current project is broken in the sense that you have no guarantee that #PropertySource is going to be processed early (actually, it won't).

Related

Is there a way to generate application properties when creating a Spring Boot project?

I'm planning to run our own Spring Initializr instance. Is there a way to have a set of application properties get written (to application.yml) when a certain option is chosen, ideally in a separate section for each of a set of predefined profiles? I've looked into customising the project-generation process in Initializr and at creating a custom starter. I've come across auto-configuration for starters, but that seems to be about what configuration to default to when this has not been provided by properties, whereas I am after generating the properties. I've also come across an example of a custom Spring Initializr instance generating files, but I need it to modify application.yml without clobbering any other modifications that may have been made to it.
Spring Initializr (the library behind start.spring.io) does not have yaml support and does not allow you to write such file automatically when the project is generated.
It's easy enough for you to add that feature though. The way it works is through a model that contributors would tune + a writer that transform the model into the target output. An analogy of this would be MavenBuild and MavenBuildWriter that generates Maven's pom.xml.
Auto-configuration is indeed completely unrelated to code/configuration generation so no need to look there.

What are the consequences of checking "Disable Auto Config Detection" in the Eclipse Spring preferences?

I mean the Eclipse preference under Window|Preferences|Spring|Beans Support
"Disable Auto Config Detection".
When this option is not checked, I notice a delay when saving Java files:
Building Workspace...
Loading ...ServerApplication
or
Loading ...DaoConfig
These messages are for Spring Boot main application classes (ServerApplication) or Spring configuration classes with #ComponentScan (DaoConfig) which are located in the workspace.
This can take a few seconds, which is a bit annoying.
When I check the above preference option, I don't notice the delay for loading these classes (at least for the Spring Boot main classes).
What are the consequences of disabling Auto Config Detection, e.g. what does this option really do, what functionality do I loose? Any pointers to documentation?
Can I speed up the save process without having to disable Auto Config Detection?
In STS3, the IDE creates an internal model of your Spring application, so that it can display a nice overview of your Spring elements in the Spring Explorer view, provide content-assist in Spring XML config files and more. In order to build up this internal Spring beans model, it needs to know where to start from when building that model. You can define those entry points manually in the properties for each project: Spring -> Beans Support. That preference allows you to define Spring XML config files and/or Spring-annotated configuration classes to be used by the IDE internally to build up that model.
In addition to that there is a mechanism to detect those files (Spring XML config files and Spring Boot application configuration annotations) automatically, so that you don't need to configure them manually. But the result is the same. Those files/classes end up being configured to be used by the IDE to built this internal model.
I guess that the delay that you see comes from building this internal beans model - this is at least what the messages indicate that you mentioned.
So far for the background. You can disable that auto-config mechanism and you don't need to configure those files/classes manually. This will result in the Spring Explorer, for example, not showing anything meaningful for those projects.
As an alternative and in case you are working mostly with Spring Boot projects, I would strongly recommend to switch to the all-new Spring Tools 4 (also available as a ready-to-use Eclipse distribution). It provides a slightly different set of features and is implemented in a different way, so that it doesn't need the expensive internal bean model creation. You should give it a try. And if you are missing something that you love in STS3 that is not yet part of Spring Tools 4, let us know.

How do I manage name spaces in a Spring Integration project with multiple flows

I have a Spring Integration project that has several flows (some where between 10-15). I would like to keep my namespace clean since several flows might have similar sounding components (for ex - several flows might have a channel named fileValidatorChannel). I think I have a couple of different options to keep names from colliding with each other:
A. Preface every component name with the flow that it belongs to. For ex - flowAFileValidatorChannel, flowBFileValidatorChannel, etc
B. Create a context hierarchy where every flow is it's own context and every flow inheriting from a master context where all the common beans/sub-flows are.
What's the better approach? Is there are better way to keep my name space clean?
To be honest your problem isn't clear.
Any Spring Integration component is a bean finally. So, their ids are just to distinguish them from other bean.
Let's imaging if you don't have Spring Integration in your application. So, you would worry about some clean naming strategy for all your beans anyway?
From other side consider to use Spring Integration Flow project:
The goal is to support these, and potentially other semantics while providing better encapsulation and configuration options. Configuration is provided via properties and or referenced bean definitions. Each flow is initialized in a child application context. This allows you to configure multiple instances of the same flow differently.

Applying settings in Spring based application in runtime

We have Spring based (Spring.NET) web application and use VariablePlaceholderConfigurer to keep some settings in a separate properties file.
These properties are mainly different values affecting business logic, like emails, timeouts, paths, etc.
Now we need to implement administrative UI to allow users to change these settings in more friendly way.
So we will move all these settings to a database.
Question: What is the best (standard, common) approach to implementing settings like I described in Spring based application? (Assuming we want changes to be effective immediately without application restart.)
It is good if we can keep our current approach when setting values as just properties of beans.
The VariablePlaceholderConfigurer is ObjectFactoryPostProcessor, which is only invoked after reading the object definitions. So you cannot simply introduce a new IVariableSource that you refer to in your VariablePlaceholderConfigurer configuration, because it will only take effect after container reload.
You have to create an IObjectObjectPostProcessor to modify properties on container managed objects at runtime.

Multiple messageSources in Spring configuration files

our web application uses Spring 2.5. It consists of several modules, each of which can bring additional Spring context files, which are loaded automatically (into one application context). We want to let each module provide additional resource bundles (for I18N support).
Spring supports internationalization by registering a bean with name messageSource in the configuration file, but this assumes I know exactly what is the fully qualified name of the class or properties file that contained the translates strings. This is a problem because other modules might have their own properties files put in a different location. So I'm looking for a way to let each module define its own messageSource with its own resource bundles and I don't know how to do it.
Does anybody know the solution to this problem?
Thanks.
I have used the Message Sources in Spring for some i18n support. In my case I only needed one so it was easy to inject the one message source I needed into the service bean that I was creating.
I was hoping to see something like what I will propose later on in the Spring sources itself. But I don't see anything that will aggregate heterogeneous message sources. If all of them will be parts of a resource bundle like property files, I'm sure you could write a wrapper for ResourceBundleMessageSource that could be dynamically updated as beans were registered.
However, if you wanted to aggregate heterogeneous MessageSources, this is what I would suggest. Create an message source aggregating bean that upon loading asks the ApplicationContext for beans of type MessageSource.class. This aggregating bean can then let each source attempt to resolve the key and format the message. Depending on how many files/msg source classes you have you may want to allow the aggregating implementation to prioritize which ones it attempts to use first. If performance becomes a problem, you could also cache which source resolved which keys so that the aggregator doesn't have to guess each time.

Resources