I have successfully implemented both polling and callback client side asynchronous examples, but now I am interested in implementing a web service with server side asynchrony. The infrastructure is Java EE using JBoss AS 6.x.
The pattern (as I understand it) that I am trying to implement would involve two web service operations, one to initiate a request and a second to check to see if a request is done and retrieve the results.
Client invokes web service endpoint operation 1 with search parameters via SOAP over HTTP.
Web service endpoint sends the request over JMS queue 1 to a message driven bean.
Message driven bean (MDB) picks up the request from queue 1.
MDB acknowledges service request by sending a message containing a correlator ID over JMS queue 2 to the web service endpoint.
(I am assuming this correlator ID will be the JMS message id generated.)
MDB acknowledges the original message to remove it from queue 1.
MDB begins long running database query, presumably building results to a temp table using the correlator ID as the
retrieval key.
Web service endpoint sends back reply containing correlator ID to the Client via SOAP over HTTP.
I am guessing that, since picking up the results doesn't involve a long query, I don't need JMS, I can simply query the database to see if results are ready. So, the second operation would be:
Client invokes web service endpoint operation 2 with correlator ID via SOAP over HTTP.
Web service queries database using correlator ID. Result code would be: no results found, operation still in progress, or
results found.
Web service responds to Client with some sort of complex structure that would combine the result code along with any results.
So, I have many questions. I have seen some references to server side support for asynchrony, but they all seem to be server specific in some way. For example, I have seen a diagram describing this first operation exactly, but it seems to be OC4J specific. If anyone can direct me to an generic example or tutorial implementing something like this, please do. Other subleties might be, should I use the JMS message ID as the correlator to return to the client? I am assuming I should use CLIENT-ACKNOWLEDGE as the JMS session mode so that the MDB can send a reply to the web service and then remove the message from the queue. Or, should I even bother? Should the web service endpoint just generate a JMS message, pop it in the queue and return the message ID directly to the service client without going through all the rigamarole of having the MDB send back a correlator via JMS queue 2? [edit: Actually, the more I consider it, it seems wrong that the web service would send a message and then, what, block on waiting for a reply on queue 2? ]
Correlation id can be generated at step 2 and immediately returned to the client. That reduces additional hops before responding to the client. Generating a persistent message into the queue should suffice. I also dont see the need for two queues. I prefer an application generated correlation id.
Related
We are in the process of designing the migration of our monolithic Java application to microservices to meet various client requirements such as scalability, high availability, etc. The core function of our application is data processing, i.e. retrieve data from a source, put it through 0 or more transformations, and finally push the result to a destination. For this reason, we are looking at Spring Cloud Data Flow running on Kubernetes and Kafka to do the heavy lifting for us, with a few custom built stream applications to handle our business logic.
One thing we have not yet figured out though is how it could handle synchronous responses to requests being sent in via an HTTP source - specifically when some processing is required before responding. For example, let us say that a request is received containing two different amounts in a JSON packet. We then pass this on to a custom "addition" transformer that outputs the sum of these amounts, and needs to return the result back to the calling party. However, because the transformer is a completely separate process that received the data by consuming it from a Kafka topic, it has no access to the original HTTP connection to respond.
Is this something that is possible with Spring Cloud Data Flow, perhaps by combining it with something like Spring Cloud Gateway to manage the HTTP connection? Or are we barking up the wrong tree completely?
It is not easy combine Async Flows (Spring Cloud Data Flow) with a Sync HTTP Flow (HTTP Requests have a timeout and Async Flow processing time is not known upfront). What you can do is return an id as response for your HTTP source and have another HTTP Endpoint to check the status of the initial request and get the result back using that. This is a polling approach.
I'm building a backend using RabbitMQ and Spring. My POST, UPDATE and DELETE endpoints works fine using my message broker (rabbitMQ).
However, I dont know how should I implement a GET endpoint using message broker. Is there any way for retrieving a database info for frontend using asynchronous communication?
Edit.: i have found the solution. You should clone the data from microservice X if you want to use it at microservice Y. Also, you have to keep this data updated sending it to Y everytime if change it at X.
Microsoft have some good stuff about microservices and it helped me a lot: https://learn.microsoft.com/pt-br/dotnet/architecture/microservices/architect-microservice-container-applications/communication-in-microservice-architecture
The problem here is that you are using a request-response protocol (http) that implies synchronous communication with a asynchronous backend technology.
The problem is the following: with http you are using a thread of the server thread pool to execute the request and return the response but because you are using a message broker the thread that handles the request is not the same as the thread that recieve the response.
There are two possible solutions, if you want to continue using asynchronous communication to handle the queries (GETs) you have to use some protocol that not use a request-response model like SSE or WebSocket. Spring could handle SSe natively returning a Flux or Mono in your controller.
Other option is to make it synchronous and make a query call to database to get the result blocking the thread until you get the data
I use Angular with Spring for internal API communication. Now I need to call external api to get some data. That external API provides callback feature, so I trigger call from Angular, call Spring rest method which, at the end, calls external API.
On the other hand I get data on my callback methods (Spring rest also), but I dont know how to transfer those data back to Angular.
Is websocket the only option?
If internal API calls are longer than the allowable client timeout, then you will need to find a WebSocket or WebSocket-like alternative. The alternative to WebSockets is to use long-polling (good example with source code here), which is essentially having the client repeatedly make requests until the original task is completed and the data can be sent. Either way, you'll need to use a pub/sub mechanism of some sort to handle multiple users, which is where things can get complicated.
Pub/sub can be complicated and I don't have an example on-hand, but essentially you must (1) have the client subscribe to a channel using a unique identifier (you can do this with CometD via a service channel), (2) evaluate the response, (3) publish the response to the client's subscribed channel, and finally (4) close the channel when it's no longer in use.
I've had some luck with CometD as a library to simplify pub/sub channel management, and it provides a good abstraction for asynchronous communication, although I haven't tried it with Spring and it might be heavy for what you want to do.
Another option that I'm less familiar with is to use Spring with STOMP. This seems to come recommended by others. Spring does provide ways to send messages to single users using STOMP: Sending message to specific user on Spring Websocket
I'd recommend following the above STOMP example.
Additional STOMP resources:
Getting Started with WebSockets (Spring)
Enable STOMP Over WebSocket
Angular2 with Stomp.js
As a side note, throttling may be necessary here, too, as with any time that you can spawn long-running threads from clients.
If you choose not to use STOMP or CometD, then a lighter solution could be to roll your own pub/sub for this single case using Spring's DeferredResult (as in Roger Hughes example), tying the subscription request to the long-poll request via a UUID token, which might also be the session ID if you choose to disallow concurrent requests per user. On subscription, the system can associate the request with a UUID and return this UUID to the client. The client can then make long-poll requests (again, as in Roger Hughes example) but with the UUID attached. The server can wait until the request for the given UUID has completed and then return the result to the client via the client's active long-poll request.
Channel management (i.e., request/UUID-tracking) can be done by clearing the channel on DeferredResult result retrieval and removing orphan channels with a separate thread acting as a GC -- or, perhaps better yet, automatically clearing orphan channels by removing them on DeferredResult completion/timeout if no active listeners exist. If you opt for the latter option, you will want to make sure that the client won't have any delay between its long-poll requests so that the DeferredResult doesn't unintentionally complete with no listeners.
I am working on a project which have many legacy heterogeneous systems. We are planing to connect them using JMS/MOM/ESB but need Synchronous web service calls from client.
i.e Request/Response architecture using web service is a requirement.
Client will make calls and wait for response.
My question is how can we implement Request/ response system which internally work on JMS/MOM to connect desperate systems?
Second question : Do any existing JMS/MOM or ESB implementations support such synchronous architecture?
first about second question: All of them support such architecture.
second about first:-)
just a brief idea:
when you send a message to target JMS Queue you have to have a unique message ID (in headers as example) then target system must answer (response) to "replyTo" queue. Then you have to have listener on that replyTo queue with filter by that unique ID and your flow must wait for response from that listener.
Something like that...
I'm attempting to develop a social network that implements publisher-subscribe pattern (kind of like Twitter does): users can follow people, therefore being notified when a new publication of their followers is sent.
All I have now is a working REST service implemented with JaxRS, running over Tomcat 7, offering services for login, register, getting profiles data and submitting posts. Servlet Mapping is done via web.xml
My JaxRS app config
RestServices
Web.xml
But the weight of the application comes from the pubsub part. And here is where things become messy.
Before speaking of technologies and implementation, the life cycle of this pubsub:
Let be A and B some users of the app and A follows (is subscribed to) B.
A navigates to his "timeline", therefore registering a WebSocket endpoint in the server from which he will receive notifications when any of the people he's suscribed to publishes anything. (A, himself, would be the topic?)
B publishes a new post, it's sent to JaxRS service via HTTP POST /post.
Server stores publication in database and then sends it to listening subscribers via WebSocket. As A is alive and listening, the publication is sent through his WebSocket/topic.
A gets notified of the new publication.
I've worked with Java built-in WebSockets (javax.websocket), Spring websockets (via STOMP) and JavaScript either built-in and SockJS. I know JaxRS has something called Server Sent Events that act like websockets but I'm absolutely lost on how to initialize and work with them.
My doubts:
1) Could I "mix" e.g Spring Websockets with my JaxRS server and how would it be initialized?
2) With JaxRS and SSE, can I dynamically create WS endpoints on the server?
Thanks in advance
Finally made a workaround using Jersey's Server Sent Events, though not supported by IE, but works for what I needed
Here is the code for the SSEProvider and SSEDispatcher
Gradle dependency
And front end connection and handlers
Also some docs on HTML5 SSE