I have a spring component that calls AWS to do some stuff. It acquires temporary session credentials lasting for <=1h to initialize the AWS service client at the start of my app. The AWS service client is set as an instance property of the bean. Then after this hour, I need to block all threads using this bean and refresh the temporary session credentials used by the service client.
Is there any recommended way to do this? Any hints/clues are appreciated
I think that it would be best (and easiest) for you to implement it as a sort of a proxy.
First, create a class for an object that will be refresh. Lets call it RefreshableProperty.
Then you need the proxy which will have following responsibilities:
It will be injected into any place that requires access to RefreshableProperty
It would have an instance of a field of type AtomicReference<RefreshableProperty>
It can have a method annotated with #Scheduled (with some cron expression) that would be invoked periodically
This method would connect to your configuration server and download new settings which would be put into a new instance of RefreshableProperty
At the end of such operation your code should swap the reference so that it points to a new object
If you need to have it being done exactly every hour then it will be a difficult task and I would strongly advise against it since it would be very tricky to synchronize this service client with your Spring Application.
Related
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.
I am using spring method level annotations #cacheable to cache the data that I fetched from database.
Can I perform caching with the above annotation at server Start up?
I tried this but it is again fetching from database not from cache.
Simply add a #PostConstruct annotation to your methods that you want to cache on server start up.
If your beans are on singleton scope, return values of methods would be cached before your application starts.
You can do this manually however, above is a very simple straightforward approach.
No. At least one request has to be made before you cache response data. That first request could either be by application user or by code itself in Post Construct as mentioned by #Pumpkin
I have a Spring Web MVC application where i need to use an external device driver which returns information in an asynchronous manner every time the device gathers some new data. We need to pass an object at the begging to the start read method. This object implements an API defined interface which declares the callback method.
The problem raises when this callback method needs to manipulate some bean in Spring's session scope. Because the callback gets called in the Thread of the driver when the callback implementation wants to access a Spring bean it yields an exception saying that the current thread is not in Spring's managed scope.
I'm wondering if there's any way to make the object which is implementing the callback interface into some kind of proxy which knows information about the context of the session which constructed it so this way it can invoke bean methods through Spring's context object?
I think you are approaching the problem from the wrong side. I guess you want the device driver callback to put some results in the user session. But this is not enough to display that data, so (guessing again) probably some long-polling is involved, looking into the session through session-scoped bean.
With this assumption I advice you to generate some sort of unique requestId every time you call the back-end driver and put that requestId both in the HTTP session and in the callback. When the callback is called, it pushes the results into some sort of map, where key is the assigned requestId. Now the client (who knows the requestId as well) can look into the map and fetch the results. You must remember about the synchronization (which is also the case with normal HttpSession).
If you have some more advanced way of notifying clients (Comet? WebSockets?) this can also be done in this callback.
Note that technically you can pass an instance of HttpSession object into the callback instance (but as you can see this does not work with Spring session-scoped beans) but passing session around doesn't seem like a good design. It is simply better to provide a level of indirection. What if, in the future, you would like to reuse that code with command-line or desktop client?
If the stateful session bean is going to passivate, its state is written to harddisk and then the bean instance will be freed to serve other request (at least this is my understanding). When the same client is active again, bean instance will read the state from hard disk to regain the state. But how the bean instance knows that for which client which file it has to read to maintain the state?
I am very new to J2EE, so please pardon me if I am asking a very naive doubt. If I need to know any other topic to understand this, please point me in the right direction.
It's best to visualize a Stateful Session Bean (SfSB) as very close to an instance of a normal Java class. You look up (or inject) an instance of a SfSB, and the container will create one for you and return the instance. You then work with that instance like you would any other Java instance.
That means that you can store the instance in to a Session, serialize it to disk, etc.
The detail is that the instance you are working with is actually a proxy to the actual, underlying SfSB instance. It's not the actual SfSB itself.
When you make a call on your local proxy to the bean, it is the containers job to manifest that bean in to memory for you. The passivation and activation of the bean is done behind the scenes for you (though you can tap in to the process through the beans lifecycle).
Any information that the container needs to find the passivated SfSB is stored in the proxy that you're working with, but this is opaque to you. You needn't worry about it.
So, in a typical web based scenario, the life cycle would be that you get your bean instance, store it in a web session, and then simply use it like normal. If the container decides it needs to passivate your bean to make room or whatever, it will passivate it automatically for you. When your user returns, your app pulls the instance from the web session, and makes its calls. At that time, if the bean is passivated, the container will activate the bean for you, again automatically. This entire mechanism is dependent on the container, yet transparent to you. The important thing for you to recall is that you must hang on to SfSB that you get from the container, like you would any java object.
The final caveat is that if you allow a SfSB to be passivated for too long, the container will automatically delete it for you.
I want to create a singleton object whose scope is basically only the request. This will be used to collect the errors and we need to send error whenever we send the response back.
Can anyone provide pointers toward this thing?
I am also using spring.
I tried using Spring container singleton object scope session or request but still my object is holding values from the earlier request
I am using this error object with AspectJ. Will that may cause problem on static binding?
how about
//sync this code
if(request.getAttribute("someKey") == null){
// create object and set it
}
If you set the Object life cycle in the Spring container to be per request then it should only exist for that HttpRequest.
Generally for direct injection containers like Spring when you set the object life cycle or object scope to be per request then it should create an new instance of the object for each http request that it recieves.
If it is not doing this then I would assume that it is more than likely something to do with your configuration.
Singleton is the defualt for the spring container when creating beans I think so you have to specifically set the object scope to per request.
Bean Scopes
http://static.springsource.org/spring/docs/2.5.x/reference/beans.html
I'm not sure that singleton is what you want here - if two requests arrived concurrently they would share the singleton object, and their errors will get mixed up.
Is it possible to create an object to hold the errors and put that in to a ThreadLocal object. The scope of the object will be constrained by the request, and access to it in the ThreadLocal object is easily achieved from within your application without having to pass a refernce to the object around.
You can use ThreadLocal.