Does spring store updated singleton beans back to the ApplicationContext - spring

Does spring application context get initialised for every http request ? In a spring web project If I modify a singleton bean in first http request then in the next http request can I get that value ?

Application Context is being initialised when the application starts. If you in any way modify a singleton bean you will get the updated value. Let's say you have a singleton object that has an integer field age = 10. And you create an endpoint to set this value and another one to fetch it. If you try to fetch it you'll get 10, but if you call an endpoint to change the value to 15 next time you fetch it you'll get 15.

Related

Does an autowired FluentProducerTemplate need to have its headers and body cleared before use within same service?

Autowired FluentProducerTemplate in a service bean will intermittently have a header set from a previous call in another method in the same service bean. I set the CamelOlingo4.keyPredicate is the header in this case.
FluentProducerTemplate producerTemplate;
UserAccount account = producerTemplate
.withHeader("CamelOlingo4.$select", "cva_useraccountid,statuscode,emailaddress,cva_firstname,cva_lastname,cva_password,cva_lastlogout,cva_lastlogin,cva_lastloginattempt,cva_lockeduntil,cva_loginattemptcount,_cva_contact_value")
.withHeader("email",username)
.withHeader("activeStatus",MSDynamicsAccountStatusCodes.ACTIVE.toString())
.withHeader("lockedStatus",MSDynamicsAccountStatusCodes.LOCKED.toString())
.to("direct:login")
.request(UserAccount.class);
And my route definition:
from("direct:login")
.id("routes.id.login")
.toD("olingo4://read/{{route.login}}?$filter=emailaddress eq '${header.email}' and (statuscode eq ${header.activeStatus} or statuscode eq ${header.lockedStatus})").log("Response from Olingo: ${body}")
.process(new OlingoProcessor());
I do fire an async request route with the keyPredicate upon successful login...
producerTemplate
.withHeader("CamelOlingo4.keyPredicate", userId)
.withHeader("Content-Type", "application/json")
.withBody(user)
.to("direct:tracklogin")
.asyncSend();
And route defined for track:login:
from("direct:tracklogin")
.id("routes.id.track.login")
.marshal()
.json(JsonLibrary.Jackson)
.convertBodyTo(String.class)
.log("JSON Body: ${id} ${body}")
.to("olingo4://patch/{{route.patch.track-login}}");
Random times, the "direct:login" route will have the keyPredicate set in the header, causing an error in my OlingoProcessor, since I'mn not getting the expected object back from the exchange body. (Olingo Object is different when querying with a keyPredicate)
Not sure if the issue lies with my implementation, the camel-olingo4 comp or the FluentProducerTemplate itself... But I do see there is a clearAll() method on the FluentProducerTemplate. I'm suspecting i need to call it whenever i use the autowired producer template within the same service bean. Just need some confirmation...
As Spring default scope is singleton, indeed the injected producer template bean instance will be reused, and the clearAll() should be called before setting headers, body, etc...
Of course, another possible solution would be to create each time a brand new producer template instance:
FluentProducerTemplate producerTemplate = context.createFluentProducerTemplate();
UserAccount account = producerTemplate.withHeader(...)
TL;DR
Does an autowired FluentProducerTemplate need to have its headers and body cleared before use within same service?
In Camel 2, yes. In Camel 3, no.
Long Story
The CamelAutoConfiguration from Camel's Spring Boot Starter create a FluentProducerTemplate with no specific scope, hence Spring's default scope singleton is applied and you have only one instance per application.
The FluentProducerTemplate is thread-safe. In Camel 2, thread-safety is achieved by storing the message body and headers in ThreadLocals. If you don't clear the headers after/before usage you may occasionally see left-overs from previous invocations. So, yes, you'd have to call clearHeader() or clearAll() manually.
The situation in Camel 3 is a bit more relaxed. There, thread-safety is achieved by producing new instances of FluentProducerTemplate whenever you call a method that would otherwise modify the template (headers, body). Clearing the values is not strictly necessary anymore as far as I can tell.

How to detect if a bean is instantiated on each HTTP request ?

I'm using the #Scope annotation with value of "request".
How do I check if the given object with the "Scope" annotation is instantiated on each http request ?
Do the object (bean) have some identifier (hashcode ) ? And, I don't mean the bean id.
System.identityHashCode(theBeanVariable)
Print the hashes and check the objects are the same or not.
You gotta believe!
No, I'm kidding. Methods I used so far:
In eclipse if you stop application on a breakpoint you can check the id of every object in Variables tab. Every new instance of object has new id. You probably can find a place in your code that is executed after every (or some) request.
If you can set some fields of this bean via a web page, go and do it and then open the same page in new tab in your web browser. If request scope is working, fields you set should have old values (the one that are set on creation of object).
Maybe these are not uber-pro methods, but may be enough in some cases and you don't have to add anything in your code.

'Reset' scoped session bean using Spring

I have a webservice with a session bean like that;
#Scope(value=WebApplicationContext.SCOPE_SESSION,
proxyMode=ScopedProxyMode.INTERFACES)
private DocumentModel docModel;
I want to maintain the state of all objects inside DocumentModel during a process and when it is over reset that object, because I don't want that the sessions keeps all the data related with that object generated during the previous process. Is possible do that in some way different than put a docModel.reset() than set all the objects inside it to null?
Thanks

How to read unique key in spring for every request

I have requirement to access a particular variable in every service and dao classes. This variable is generated in controller class and passed to service layer and dao layer.
e.g. in Service layer : getService(String key)
in Dao : getTable(String key)
This key is basically used to store error codes in a map with the reference of the key. This key is generated for each service when the request is received in the server. This key is a random number.
Is there a way to fetch this key from spring context so that it can be fetched every time it is required to be used, Instead of passing it every where.
I think its better to pass the value via method argument through each layer. If you are trying to minimize the number of arguments in you methods, it is better to Introduce a Parameter Object.
However, if all the beans that required the value of variable are defined with Request Scope, then you could define a VariableHolder<T> bean to store the value of the variable.
The controller with call variableHolder.set(value) and all the other beans will call variableHolder.get() to obtain it.

Spring Request and Prototype Scope?

Below are the definitions of prototype and request scope in Spring.
prototype
Scopes a single bean definition to any number of object instances.
request
Scopes a single bean definition to the lifecycle of a single HTTP request; that is each and every HTTP request will have its own
instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
As per my understanding In case of prototype scope , some pool will be maintained by core container. It will serve the bean instance from that pool.
In case of request scope, new bean will be served for each http request. Please correct me if there is some dicrepency in understanding?
If above statements are true, then if bean is holding some state then the scope should not be defined as prototype rather it should be defined
as request. Correct?
Prototype creates a brand new instance every time you call getBean on the ApplicationContext. Whereas for Request, only one instance is created for an HttpRequest. So in a single HttpRequest, I can call getBean twice on Application and there will only ever be one bean instantiated, whereas that same bean scoped to Prototype in that same single HttpRequest would get 2 different instances.
HttpRequest scope
Mark mark1 = context.getBean("mark");
Mark mark2 = context.getBean("mark");
mark1 == mark2; //This will return true
Prototype scope
Mark mark1 = context.getBean("mark");
Mark mark2 = context.getBean("mark");
mark1 == mark2; //This will return false
Hope that clears it up for you.
You are off. Prototype is described in the docs here as
"The non-singleton, prototype scope of
bean deployment results in the
creation of a new bean instance every
time a request for that specific bean
is made."
Your description of request scoped beans is accurate.
Probably just got the wires crossed vis-a-vis prototype vs singleton.
Prototype scope creates a new instance every time getBean method is invoked on the ApplicationContext. Whereas for request scope, only one instance is created for an HttpRequest.
So in an HttpRequest, if the getBean method is called twice on Application and there will be only one bean instantiated and reused, whereas the bean scoped to Prototype in that same single HttpRequest would get 2 different instances.

Resources