Selective bean loading - spring-boot

I have a library and different applications that use that library.
The problem comes that each application uses a part of the library, not all.
So how can I avoid loading the beans in the application that are not used?
thank you very much

I can see 3 options.
spring profiles (https://www.baeldung.com/spring-profiles) - mark your beans as activated by one or another profile and let applications define the profile to use.
#ConditionalOnProperty (https://www.baeldung.com/spring-conditionalonproperty) - mark your beans as activated by specific value of specific property and let applications define those properties.
A bit more complicated - turn your library into spring boot starter and define multiple auto configuration classes: https://www.baeldung.com/spring-boot-starters

Related

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.

Using SpringBoot as an application loader

I have a spring-boot app that acts as a small framework for other apps. It provides a couple of JMS queues and a DAO layer to retrieve and store data from a common set of data stores. The problem is that the original developer of this framework app is scanning all the package "com.mycompany" (rather than com.mycompany.framework) so that it can load the beans of the specific app that may be declared under com.mycompany.myapp1 or com.mycompany.myapp2 an which JARs are bundled together with the JARs of the framework.
We only load a single app in the JVM (app1 or app2), but these apps may share other libraries and sometimes we end up with beans in the context that we don't need. (these may be needed in app1 but not in app2)
So, what would be your advice ?
My problem is similar to what was described here:
https://github.com/spring-projects/spring-boot/issues/3300
I am debating if each app should be aware of the framework and load it. Or if the framework should instantiate a class loader and create a new Spring context loading the app specific code as suggested in the link above.
Perhaps you should consider leveraging some of Spring Boot's Auto Configuration capabilities such as #ConditionalOnProperty or #ConditionalOnClass in your framework. That way, you can only actually enable certain beans if and when the application using your framework takes some specific action (e.g. has a given jar on the classpath, or sets a configuration value). For reference check out: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-developing-auto-configuration

How to load beans based on custom properties

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).

Enable/ Disable different sets of Controllers in based on mode specified at startup Spring MVC

While starting my Spring MVC war I need to specify the mode.
Based on mode it should start different set of controllers.
Is it possible to do the same by specifying mode/ applicable controllers
while starting it?
A similar question Spring MVC web application - enabling / disabling controller from property only talks of test but I need to have various combinations and start all controllers as default.
Spring in general has a profile mechanism that lets you register different beans in different environments
When you bootstrap it according to doc, distinguishing controllers is as simple as annotating them on a class level with e.g. #Profile("mode1") vs #Profile("mode2")

Is it bad practice for a spring-based jar project to provide a bean configuration file?

If you have a library containing Spring beans that need to be wired together before an application can use them, does it make sense to include any sort of bean configuration file in the JAR (such as the /META-INF directory)? The idea is to give the application the option of importing this into its master Spring context configuration.
There may be more than one way to wire these beans, so I could provide a bean configuration file for each of the standard ways in which you'd typically wire them together.
Or, do I force the application to wire these up explicitly?
If it helps, the specifics of my problem involve a library I created to encapsulate our product's persistence layer. It contains Service, DAO and model beans. The DAO implementations currently use Hibernate (this probably won't change). Some of the DAO implementations need different kinds of Strategy beans injected into them (database encryption logic), depending on the type of database we are deploying on (MySQL vs SQL Server, etc). So we have potentially a few different configuration scenarios. I could also provide datasource bean configurations, relying on property substitution at the app level to inject all the particulars needed by the datasource.
Thanks for your input!
In this case, it's a good idea to provide some beans files, either as examples for documentation purposes, or as fully-fledged files ready for including into a wider context.
If your beans' wiring can get complex, then you shouldn't really leave it entirely up to the library client to figure it out.
This is more of a documentation and education task, really.

Resources