I'm trying to use Archaius with my Spring application to reload dynamic system properties without having to do a full restart of the application. I'm planning on implementing this using Archaius' callback mechanism. Once Archaius detects a change, in the callback method I plan to do a bean refresh to pick up the new property changes.
The problem is, there are a few singleton beans that are created on start-up which are using the property I want to reload. I also have a few classes which autowires this singleton bean.
Is there a way of doing a refresh of the bean and all its dependencies without perform a restart or an applicationContext.refresh()?
Or does Archaius have a built-in library which can help with Spring integration?
Related
I am a new user of Spring framework. I am facing some confusion in understanding the difference between core spring framework and spring boot. As far as I understand, Spring boot is a framework which performs the initial setup automatically (like Setting up Maven dependencies and downloading the jar files) and comes with an embedded Tomcat server which makes it ready to deploy in just one click., Whereas, Spring MVC requires manual setup. All the tutorials that I watched for core spring show bean configuration using bean factory which configures the beans using a .XML file. In Spring boot, this bean configuration file is absent. My question is, what is the use of this bean configuration file? I did not find any legitimate use of this file in making a REST service with spring. I didn't see any use of the Application Context, Bean Factory in creating web application. Can someone point out how can bean factory be used in Spring web apps? Is there any fundamental difference between core spring and spring boot other than the additional components?
The Spring application context is essentially the "pool" of beans (service objects, which include controllers, converters, data-access objects, and so on) and related information that define an application; I recommend the reference introduction. In theory, you can get complicated with the context setup and have hierarchical organization and such, but in most real-world cases you just have a single plain context.
Inside this context you need to install all of the beans that provide the logic for your application. There are several possible ways to do this, but the two main ways are by providing XML files with have directives like bean (define an individual bean) or component-scan (automatically search for classes with certain annotations, including #Controller) and by using Java classes annotated with #Configuration, which can use annotations and #Bean methods.
The XML style is generally older, and newer applications mostly use Java configuration, but both provide entries that are collected into the context, and you can use both simultaneously. However, in any application, you have to provide some way of getting the registration started, and you will typically have one "root" XML file or configuration class that then imports other XML files and/or configuration classes. In a legacy web.xml-based application, you specify this in your servlet configuration file.
Spring Boot is, as you said, essentially a collection of ready-to-go configuration classes along with a mechanism for automatically detecting configurations and activating them. Even this requires a configuration root, though! This is the #EnableAutoConfiguration instruction, frequently used through its composite #SpringBootApplication. The application context and configuration mechanisms work normally once Boot finds them and pulls them in. Spring knows where to get started because you give it an explicit instruction to build a context starting with that entry point, usually with SpringApplication.run(MyApplication.class, args).
The embedded-server configuration just happens to be a particular set of configuration that is really useful and comes with one of the Boot starter packages. There's nothing there that you couldn't do in a non-Boot application.
I use Flyway in my application and it is configured as Spring bean, which performs migration as init-method(example configuration can be found here in the bottom). Of course migration should be performed before any app's interaction with database.
That's why my datasource bean depend on Flyway bean. But i create Flyway bean conditionally using #Profile, because i do not want to create it using the same app's context in integration tests.
The problem is that when i use test profile which does not create Flyway bean, datasource instantiation fails with NoSuchBeanDefinitionException, because it depends-on="flyway" which is not created with current profile. Can i somehow make spring to ignore this depends-on dependency, if related bean does not exist? If no, what is the way to decouple Flyway bean from context when i use it under test profile?
What would be the best way to handle a situation, where new Spring context is introduced to application during a runtime, and server restart is not an option?
I have an application where some beans are registered to other bean called "manager" when context is created. Now, should there be new functionality needed later, I have a Spring configuration file defining beans for the new functionality, and these beans should register them selves to "manager", which is already created. This works fine if the new file is added to classpath and server is restarted, but how to achieve it without restarting?
I guess I should make Application container somehow notice new context files and process them like during startup. But is that possible?
Have you considered combining spring with a framework like Apache Felix?
http://felix.apache.org/
Our Java Web application loads with over 1000 plugins that are all registered by us as Spring beans using the ApplicationContext#registerBeanDefinition() method. These beans often have other dependencies which we also register as spring beans using the same method (for a total of about 7,000 Spring bean definitions...not including our core application code).
The problem is that the startup time is long (approximately 6.5 minutes of just plugin bean definition loading). We would prefer to spread this load time out over a much longer period while our app is actually processing other requests utilizing plugins that have already had their bean definitions registered. Most of the plugins are seldom used. Thus, we would really like to lazily register our bean definitions (this is different from lazy-init of singleton beans which we already do today). However, this seems costly with any existing Spring ApplicationContext that supports 'hot' refresh() calls (as the Spring documentation refers to it).
The Spring ApplicationContext classes that support 'hot' refresh start by destroying all of the singleton beans. Most of our plugins are singletons, so each call to refresh() would cause most of our plugins to be destroyed and then recreated...costly. If we don't call refresh, then our newly loaded plugin beans will not be post-processed (e.g., AOP, etc...).
We can guarantee that when we are forced to load another plugin, we will also load any of its dependencies that are not already loaded. So, we would never ben in a situation where a loaded bean definition is invalid.
It seems to me that this calls for a new type of Spring ApplicationContext that supports 'hot' refresh, but only for the purpose of adding new bean definitions. Preexisting bean definitions are not removed/reloaded, and not re-processed by BeanFactoryPostProcessors on subsequent refresh() calls, and pre-existing singletons are not destroyed!
Does this already exist?. Is there a better solution that I'm overlooking?
This sounds like you're looking for #Lazy.
4.4.4 Lazy-initialized beans
A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup.
I am implementing a web application using Spring. I am using Spring's ContextLoaderListener, to load up my application contexts, and Spring's DispatcherServlet, to load the relevant beans from {name}-servlet.xml, which refer to the beans in the main application context. I want to be able to integration test these Spring configurations outside of the container to validate everything is wired up correctly before I deploy to Tomcat. However my application requires some scheduled background processing when running in the container. In a regular HttpServlet I would simply implement init() and destroy(). All the suggestions I have read suggest using an InitializingBean for that kind of initialization.
However, if I use an InitializingBean, afterPropertiesSet() gets called whether I am inside the container or in integration tests - and outside the container, I don't have access to the resources that background task needs. Is there a better way to perform the tasks I would normally perform in init() and destroy() so that they will only run when deployed as a webapp?
Have you considered using a test spring config file that overrides the bean implementing your background process?
This way everything else in the spring configuration would work normally except for the one overridden bean.