Need cache per request capability in Java - java

I am developing REST APIs using Java Spring framework.
When calling these APIs, I have a need to check for permissions, where I will need to make a call to the DB to get the permission data. The thing is, there are multiple areas checking for permission in a single request, and I do not want to make multiple calls to the DB, so I intent to cache the permission data just for that single request.
I have tried creating a request scoped bean, which works, but not for all cases. There are times where the request scoped bean cannot be created, for example when running a scheduled code using #Scheduled annotation, simply because it is not a request. Another case is when checking for permissions using WebSecurityConfigurerAdapter, the bean is also not yet created at that time.
So, I looked into another possible solution, which is this: https://github.com/rinoto/spring-request-cache. If I use this solution, I will need to remove the cache from threadLocal every time an operation is complete. I am not very comfortable of using this solution since I'm not an expert in Java, and I've read that it is not recommended to use threadLocal as cache.
What's the best way to achieve my goal? My ask is simple, cache some data only for that request. Is there any library that supports it?
I find it hard to believe that my ask is not a normal use case, or is it not a normal use case?

You can use ThreadLocal as a cache in this case. No need to clear. As per the documentation
Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the {#code ThreadLocal} instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).
eg: ThreadLocal<Map<String, Object>> THREAD_LOCAL_DATA = ThreadLocal.withInitial(HashMap::new)

Related

Recommended approach when restoring a Spring State Machine instance

I am planning to use Spring State Machine to control an execution workflow. The system is expected to receive requests from multiple users and each user may be assigned to multiple workflows. My initial idea was to have one instance of SM per workflow and every time an user perform a step in the workflow, I would use its identifier to restore the machine from a persistent storage, input the new event and store the updated SM.
I've read around that initialising a SM is an expensive operation and some people recommend having a single instance of it, but "rehydrate" that instance with some data. My understanding is that this would be more effective, but I think it would become a "blocking" operation, in other words, one workflow would need to wait for the previous one to be finished/released before-hand. Since I'm newbie on this topic, can anyone shed some light on the best alternatives for my use case and perhaps pieces of code to illustrate the differences? (PS: I'm using v2.4.0)
I was first implementing the "rehydrate" mechanism because as you said, it made sense and was also used in the "persist" example of spring-statemachine.
Howewer, running performance tests against my API showed that using a single instance fails when using the StateMachine as an #Autowired Bean with the prototype scope as it is described in that example. What happens is that simultaneous requests against my API override that Statemachine Bean and the first request fails as the statemachine changes when writing back to the DB (i used redis).
So now I actually build a fresh statemachine everytime a request comes in and rehydrate that object:
public String getStatesGuest(HttpServletRequest httpServletRequest) throws Exception {
StateMachine<States, Events> stateMachine = stateMachineConfig.stateMachine();
resetStateMachineFromStore(httpServletRequest.getSession().getId(), stateMachine);
return convertToJson(buildGetStateResponse(stateMachine));
}
It still is very performant, I was testing with around 30 reqs/s and still got a median of 12ms. (Docker with 2 Cores for spring boot, 1 Core for redis).

Global Resource Object in Spring

I'm just getting into Spring (and Java), and despite quite a bit of research, I can't seem to even express the terminology for what I'm trying to do. I'll just explain the task, and hopefully someone can point me to the right Spring terms.
I'm writing a Spring-WS application that will act as middleware between two APIs. It receives a SOAP request, does some business logic, calls out to an external XML API, and returns a SOAP response. The external API is weird, though. I have to perform "service discovery" (make some API calls to determine the valid endpoints -- a parameter in the XML request) under a variety of situations (more than X hours since last request, more than Y requests since last discovery, etc.).
My thought was that I could have a class/bean/whatever (not sure of best terminology) that could handle all this service discovery stuff in the background. Then, the request handlers can query this "thing" to get a valid endpoint without needing to perform their own discovery and slow down request processing. (Service discovery only needs to be re-performed rarely, so it would be impactful to do it for every request.)
I thought I had found the answer with singleton beans, but every resource says those shouldn't have state and concurrency will be a problem -- both of which kill the idea.
How can I create an instance of "something" that can:
1) Wake up at a defined interval and run a method (i.e. to check if Service discovery needs to be performed after X hours and if so do it).
2) Provide something like a getter method that can return some strings.
3) Provide a way in #2 to execute a method in the background without delaying return (basically detect that an instance property exceeds a value and execute -- or I suppose, issue a request to execute -- an instance method).
I have experience with multi-threaded programming, and I have no problem using threads and mutexes. I'm just not sure that's the proper way to go in Spring.
Singletons ideally shouldn't have state because of multithreading issues. However, it sounds like what you're describing is essentially a periodic query that returns an object describing the results of the discovery mechanism, and you're implementing a cache. Here's what I'd suggest:
Create an immutable (value) object MyEndpointDiscoveryResults to hold the discovery results (e.g., endpoint address(es) or whatever other information is relevant to the SOAP consumers).
Create a singleton Spring bean MyEndpointDiscoveryService.
On the discovery service, save an AtomicReference<MyEndpointDiscoveryResults> (or even just a plain volatile variable). This will ensure that all threads see updated results, while limiting them to a single, atomically updated field containing an immutable object limits the scope of the concurrency interactions.
Use #Scheduled or another mechanism to run the appropriate discovery protocol. When there's an update, construct the entire result object, then save it into the updated field.

Strategies for exposing user identification from a REST endpoint back to the data-access/repository layer

The background: there is a requirement to attach auditing data to persisted entities, basically creation-timestamp + user ID and last-update-timestamp + user ID.
I'm not keen on passing the user ID as a method parameter through all layers/components. So I need to somehow pass user identifcation (derived from HTTP headers, the details are unimportant) through a REST endpoint (using RESTEasy, but that's probably not important, either) back to the data access/repository layer.
I've thought of using ThreadLocal but it feels a little hackish and might fail in a non-blocking IO environment. Maybe I'm wrong about that, not sure.
I also have a vague idea that AOP could help, though I'm not well-versed in AOP so not sure.
Any strategies appreciated, with or without code.
You can use entity lifecycle callback methods for your requirement: #PrePersist, #PostPersist, #PreUpdate, #PostUpdate.
It is one of the auditing strategies mentioned here.
It turns out that Spring's SecurityContextHolder is a reasonable place to do this (don't ask why the application isn't already integrating "properly" with Spring Security). It's basically the ThreadLocal option but with some nice interface around it.
The tradeoff is that you need to be acutely aware of the thread-bound nature of this solution. A controller that somehow uses other thread to do the work that needs the user context, will need to take some steps to make sure those threads can get it since they don't, by default, inherit the ThreadLocal. There is a mode you can set on SecurityContextHolder that will use inheritance of the ThreadLocal in any newly created threads, but that does not help if a thread pool is used (since threads won't be created by the request thread but rather pulled from the pool). Even then, most thread pools provide a way for the client thread to do "something" when obtaining and releasing threads, so it's possible to pass the security context on that way.

Reading the same ResultSet from multiple threads

In the database, I have a definition table that is read from the application once upon starting. This definition table rarely changes, so it makes sense to read it once and restart the application every time it changes.
However, after the table is read (put into a ResultSet), it will be read by multiple handlers running in their own threads.
How do you suggest to accomplish this?
My idea was to populate a CachedRowSet, and then create a copy of this set (through the createCopy() method) for each handler every time a new request comes.
Do you think this is wise? Does this offer a good performance?
Thanks.
It may be better for you to use the singleton pattern. This would allow you to create a single class that all of your threads could access to get the object that they needed. This could also allow you to not have to shut down your application whenever changes are made. One way to accomplish this is to have a class where you have get and set methods for the information you need. And another class that will give out references of that object.
The class that gives out references could have a private constructor, and a getInstance method that will return a reference to itself to ensure that only one exists. This would also give you some other options regarding what you can do when things change.
Ok, if you control access to the resultSet, and you don't care to update the result set until you restart the application, then i would suggest wrapping the CachedRowSet in a custom class. One possible way to do this is to have a wrapper class that is a singleTon and provide it with getter methods so that other threads or classes for that matter can access it. That way you remove the need to make a copy and remove the dependency on CachedRowSet implementation. Creating a copy would cause unnessary overhead. Imagine, in the way you described above, if you had 1000 threads accessing your result set, you would call createCopy() 1000 times thus creating a 1000 copies of the same resultSet.
I think it is a pattern to read the configuration table into a static data structure (ConcurrentHashMap) and then let the threads to look it up.
You can ensure that there is no write race at startup by populating the reference map from a Servlet.init() - it is guaranteed to execute once per servlet.

Java Session Like Object

I have been developing a project and in this project i have designed my code to do the same job after a specified time interval continuously. The job that wanted to be done has a lot of distinct cycles. The interval is small to execute them normally thus i used threads. Until that point everything is clear for me.
To decrease the process and information transaction i wanted to put an session like object that holds the given data and provide it to any thread at anytime. With this object i plan to not query the same configuration information from database at everytime but if it exists on the session take it else query and store on session.
I'm not sure how to implement this structure.
Regards,
Have you looked at ThreadLocal?
That depends. There are several ways to keep and pass information in Java.
Applicationwide: declare it static and/or load it in a static {}.
Threadlocal: make use of ThreadLocal<T>.
Objects: put data in wrapper objects (javabeans?) which you just create once and pass around as c'tor/method arguments.
In your case I think either 1 or 3 is applicable. A real "session" is usually threadlocal, but your functional requirement ("provide to any thread at anytime", "configuration information") makes me think you're rather looking for an applicationwide constant.

Categories

Resources