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
MyEndpointDiscoveryResultsto hold the discovery results (e.g., endpoint address(es) or whatever other information is relevant to the SOAP consumers).
- Create a singleton Spring bean
- 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.
@Scheduledor 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.