Spring properties hot reloading - java

In a project, I have a org.apache.commons.configuration.PropertiesConfiguration object registered as a Bean, to provide configuration values around the application, with hot-reloading capabilities.
Example: I defined a DataSource singleton Bean. I then created a ReloadingDataSource object, which wraps and delegate to the "real" DataSource, and each time the configuration file changes, it is able to recreate it in a thread-safe manner.
I'd like to do something similar for simple properties values.
I'd like to create a simple, Autowireable object that delegate retrieval to the Apache PropertiesConfiguration Bean.
The usage should be similar to:
#Property("my.config.database")
private Property<String> database;
And the call site would simply be:
final String databaseValue = database.get()
You'll say, just pass around the PropertiesConfiguration object. Maybe you're right, but I'd like to provide another abstraction over that, a simpler-to-use one.
I know that with ProxyFactoryBean it is possible to create an AOP proxy for method calls. Is this the right path, or are there better alternatives? Maybe pure Spring AOP/AspectJ?
I don't want to use Spring Cloud or similar dependencies.

Spring Cloud will recreate the beans, so keep in mind whatever solution you come up with, if you have another bean which only reads this value once for instance when it is initiated, it won't re-initialize itself, that is the problem Spring Cloud Config takes care of.
AOP only works at the method level as I understand, so you can definitely intercept a call to somebean.getFoo(). But within somebean, there is no way to proxy calls to the variable itself: somebean.foo. You would have to reset foo every time your PropertiesConfiguration changed, and again keep in mind that, if anything else needs the new value of foo you would need to handle this or bite the bullet use Spring Cloud.
The overhead you have with changing stuff at run-time to avoid a re-deploy should really be thought carefully about. For Netflix, this makes sense because they have thousands and thousands of servers. But for smaller players I can't see the justification, the decision adds much complexity. Nightmare to test.
Do you test changing your configuration at run-time or accept the risk and assume it works?
Do you test changing from A -> B whilst under load of a user performing a transaction to the database?
Test other raise conditions where foo is changing?
Some things to think about.

Related

Spring: Scoped fields

I wrote this idea on the Spring JIRA and even though I know this is not a key feature and has minor priority, I'd still expect some answer by now. I publicize the idea, because I want to know what you guys think about it, if it's cool and I should implement it myself, or is the need for this is a sign of bad architecture.
So the idea itself is - as the title suggests - is a field in a Spring Bean, which has a different scope then the bean itself. We already have something like this, in the shape of scoped proxies, however it works only for bean dependencies. I might want to store a list of Strings of session scope in a bean of singleton scope. I, then have to create a new bean, with scope of session for one field and some functions to use that field. It seems a waste of code and I'd find it bad, because I wouldn't be able to use that bean anywhere else, because it'd already have that data the first class put into it.
I could rephrase the mess above and say that I want to have named beans with arbitrary type (so not necessarily spring beans) and on top of the scope we configure it to have, that field would also be different for every instance of the parent class.
This could make a field instance broader than a prototype scoped bean, but also less broad then the actual scope we'd like to use it in. Kind of a middle ground.
Here is the JIRA issue I wrote: https://jira.spring.io/browse/SPR-16971
In my understanding, Scopes only work with Dependency Injection as it's the DI Container that decides if it should return a new instance or an already existing one. So everything that is #Autowired can be scoped.
I can't imagine how scoping a normal field would work. If I change it, should it change in all other objects that "use" it? I would have to be some kind of proxy object then and neve a primivive value. If on the other hand you have a proxy object, why not use the currently available autowire mechanism.

Is there a way to store java variable/object in application context without xml or properties file

I want to store a particular variable (String or Object) in application context in spring boot application. But I don't want to use an xml or properties file for storing it.
There will be a function which will store the data in application context. I should be able to retrieve it, modify it, delete it or add more data.
Basically I want to store data in application context after its initialization has been done.
If you create a class and put #Configuration annotation over it, and declare some beans with #Bean annotation, they become application managed beans.
#Configuration
public class ConfigurationClass {
#Bean("myString")
public String getString() {
return "Hello World";
}
}
Then anywhere from your code you can call AnnotationConfigWebApplicationContext.getBean("myString") to get your bean.
Now there could be concurrency issues (as mentioned by davidxxx ). For that you can use SimpleThreadScope. Look at this link to learn how to register it with application context and where to place that annotation (or google it).
Or if you don't want to deal with that, then a #Scope("request") should help. The bean with #Scope("request") would be created for every new incoming request thus it’s thread safety is guaranteed since it’s created every time a new request comes in.
As a general way, you should avoid creating stateful services.
Storing application data in the server memory makes it harder to be resilient, autonomous but also distributed and scalable.
Besides, Spring Beans are not designed to be stateful.
If you do it, you may have race conditions without the required synchronization.
About your need, if you want really to have a stateful service at startup, create your own singleton instance and synchronize the methods that should be thread safe.
Then access it from anywhere.

Quartz in Spring; jobDataAsMap serialization for multiple-use job bean

I have an extension to QuartzJobBean that takes two parameters:
public class FileListProcessorJob extends QuartzJobBean
{
transient static final Logger logger = Logger.getLogger(FileListProcessorJob.class);
FileListProcessor fileProcessor; // with setter
FileListProcessor fileProcessor2; // with setter
// ...
}
I have 4 quartz jobs in this application that use this bean; it is the number of times I have that processes a set of files from a folder, then does another set.
It works fine in my test environment, but when I moved it to development, I had to configure Quartz for a database datasource since it was to work in a cluster. When I did that, the runtime started telling me that "fileProcessor" was not serializable. I've tried to make it serializable, but the message is still there.
There are three different bean classes and four different beans loaded under fileProcessor; I've been over all of them to ensure they are serializable, but the message still appears. The message also appears to indicate that the log4j Logger is the non-serializable entity, but I can't see how that is. I made it transient in one pass, no difference.
The standard answers to the serializable problem I find on SO and elsewhere involve moving making a call within the job bean to the job execution context, passing in the reference through SchedulerContextAsMap. But, as near as I can tell, this depends on having globally unique names for the parameters to which to load the globally unique bean names, which doesn't work as I have this set up. I re-use the parameters since I re-use the bean itself.
I'm new to Spring design, but I thought this was the way it was supposed to work -- reusable components, configured with XML to avoid having similar classes slightly modified to do different things. So how can I make my 4 jobs work? Do I have to copy-and-paste them, then slightly modify the names so they're different, and unique in the configuration? Or is there some other piece I am missing and can use here?
There were two levels of problem to be solved; getting something to be serialized takes some painstaking examination and alteration of code, and the clustered environment writes serialized forms of the beans to the database and then uses them in preference to (or in place of, or addition to, I'm not sure) the spring/quartz configuration files. Once I got ALL the serialization necessaries done, and wiped the database records of all the jobs that had been stored there, it worked more like I had expected.

Alternative to Spring's #Configurable for performance reasons?

I am using #Configurable beans for non-managed spring instances in a section of code that must be highly performant. We are using a lot of non-managed beans with the new operator, and in our profiling we have noticed that the use of the #Configurable annotation is slowing things down quite a bit.
Just for this specific section, we would like a faster way of pulling beans from the context (just a direct applicationContext.getBean()). I know we give up IoC doing this, but this is a special scenario and not a normal pattern.
We are using CTW for the weaving, but I wanted to know what mechanism spring is using behind the scenes to get the application context so we can simply grab it and use getBean? A static application context? Is it stored in threadlocal somewhere?
Aspects are singletons managed by AspectJ. When you put an aspect in your Spring configuration file Spring doesn't actually create the aspect. Instead it obtains a reference to the aspect using aspectOf().
This means that (at compile time when you do your weaving) your #Configurable annotation gets hooked into the singleton AnnotationBeanConfigurerAspect. Then when you load your application context, Spring obtains a reference to that same singleton aspect and calls the setBeanFactory() method on the aspect (since it implements BeanFactoryAware).
This magic can lead to trouble of course. If you had two application contexts then the second would overwrite the configuration of the first which can be terribly confusing.
To answer your question directly this means that all you have to do is create a new aspect that implements BeanFactoryAware (here is the code for AnnotationBeanConfigurerAspect which you can use as an example) and then "instantiate" that same aspect in your spring configuration file and your aspect will now have access to the bean factory.
If you're going for performance then please note that the above is not much cleaner than creating a static reference to the BeanFactory and instantiating that when you start your application so you might as well do the static reference as it is simpler.

Spring, create a bean from deserializing

I've not used Spring too much, so I might be missing something obvious. Anyway, this is the question:
Say you have a Spring managed bean that is a networking client. After you call a method on it you get some object back, say it is a List
Now I want to process that List into something more useful for the rest of my application, say it is of a MyBusinessBean type.
How do I avoid doing a
new MyBusinessBean(List<String> info)
?? If I do this it becomes an object that is not part of the context.
I'm doing something like:
MyBusinessBean myBean = (MyBusinessBean) applicationContext.getBean("myBusinessBean", info);
However I keep reading everywhere that this is a signal of something not being done properly, since I am making my code context aware. What is the proper Spring way of doing this?
The second way is what you do in Spring. Calling "new" means you're breaking the model.
But don't assume that every call to "new" is eliminated by Spring. Every object need not be under Spring's control. Sometimes you just gotta call "new", usually in the scope of a single method. Create the object, use it, GC it - no Spring bean factory needed.
If you want to give an object in your app access to that List after serialization, simply pass the reference. You don't need the Spring bean factory in the situation you've described, because you've already got the serialized the object from the server.

Categories