Request right after Response? - java

I am a bit lost with the following scenario:
My webservice consumes POST requests with form data. I have to reply with 200 OK or otherwise the senders thinks the request failed.
Immediately after answering with 200 I would like to proceed to call another webservice on a remote host with some of the data I have just received.
My webservice consumes the POST request with the #GET annotation. That works I can read all the form data. To call the other webservice I used the Jersey Client API. That works fine too.
I just can't figure out how to switch from switching from one call to another. Everything is programmed with Jersey 2 and deployed in Tomcat, so no real Application Server. There is no full Java EE stack available.
Am I missing some middleware? Do I need to implement a custom event-loop or some message broker?

Not sure if there's any "standard" way to handle this, but there's a CompletionCallback we can register with an AyncResponse.
CompletionCallback:
A request processing callback that receives request processing completion events.
A completion callback is invoked when the whole request processing is over, i.e. once a response for the request has been processed and sent back to the client or in when an unmapped exception or error is being propagated to the container.
The AsyncResponse is meant to handle requests asynchronously , but we can immediately call resume to treat it like it was synchronous. A simple example would be something like
#Path("/callback")
public class AsyncCallback {
#POST
#Consumes(MediaType.APPLICATION_JSON)
public void postWithAsync(#Suspended AsyncResponse asyncResponse,
SomeObject object) {
asyncResponse.register(new CompletionCallback() {
#Override
public void onComplete(Throwable error) {
if (error == null) {
System.out.println("Processing new Request");
} else {
System.out.println("Exception in Request handling");
}
}
});
Response response = Response.ok("Success").build();
// Carry on like nothing happened
asyncResponse.resume(response);
}
}
You can see more explanation at Asynchronous Server-side Callbacks

Related

How do I not lose my RequestAttributes on new thread?

Using Spring 4, in a simple POST API, I am attempting to immediately return a response and continue some more processing in the background.
#RestController
#RequestMapping("/somewhere")
public class SomeController {
SomeService someService;
#PostMapping(value = "/something")
public ResponseModel getResponseAndDoOtherProcessing() {
ResponseModel response = someService.getInitialResponse();
// Async function
someService.doOtherProcessing(response);
return response;
}
}
The first function getInitialResponse() would return an object to be sent back to the client but I want to do more processing using the response I sent.
So I define an Async function for my controller to call on another thread as to not wait on it for sending the response to the client (#EnableAsync is on a configurable file):
#Async
#Override
public void doOtherProcessing(ResponseModel) {
// do some stuff
...
// get the request attributes for some other pieces
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
...
}
But since this on another thread, it looks to lose the request attributes:
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
I have searched a few things such as using MODE_INHERITABLETHREADLOCAL and read some debugging pieces such as this but haven't had any luck.
How do I keep the scope of my request to do other processing? Can anyone point me in the right direction?

Server Sent Event with Spring with having a thread being freed from request

I need to show off an example of server sent events. I learned about it in a spring talk. People used Webflux there to show the reactive principles. I understood the part on how this will free thread resources because the request thread won't be blocked until the job is done and the server returns the response.
I have an example here but actually I don't really know how I can make this thread resource example be clear enough.
I do not want to use the WebFlux framework here. Just need to know what to put into a separate thread here - if necessary at all?!
As you can see I have a GetMapping to subscribe to the event stream. And then I have a GetMapping to launch or fire an event. This example is fast for sure but should be considered as heavy database call.
So I actually need to have the whole logic be separated in another thread right? So the request thread is free as soon as possible?
#RestController
public class EventStreamRequestHandler {
#Autowired
ObjectMapper objectMapper;
SseEmitter sseEmitter = new SseEmitter(1000000L);
#GetMapping("/get/event/stream")
public SseEmitter getStream() {
return this.sseEmitter;
}
#GetMapping("/launch/event")
public void fireEvent() throws IOException {
Person peter = new Person("Peter", "25");
String valueAsString = objectMapper.writeValueAsString(peter);
SseEmitter.SseEventBuilder sseEventBuilder = SseEmitter.event()
.id("foo")
.name("awesome-event")
.data(valueAsString);
sseEmitter.send(sseEventBuilder);
}
}
Yes, Server sent events are supposed to send messages to the client asynchronously without client keep on polling for message.
The sending of messages from client to server needs to be done asynchronously. With the way you have done it. When a GET request is sent to /get/event/stream an SseEmitter will be created but messages will only be sent when a GET request is sent to /launch/event. And the GET request thread for /launch/event will be used to send the message.
Sometime back I wrote post to send SSE messages using a different thread. I hope this helps.
But I don't recommend storing the SseEmitter in an instance variable as it will overridden by multiple requests. You must at least make it ThreadLocal

How to invoke async controller logic after returning response using Spring?

I need to process request asynchronously in time - after receiving request I must return a response with status 200 to confirm that the request have reached it's goal, and then proceed with some magic to happen in service. I tried few ways to reach it, but every time response was sent after logic part ended in some other thread.
Is there a way to reach it using Spring? Or should I rather think about other approach to this problem?
The Spring Framework provides abstractions for asynchronous execution and scheduling of tasks
You can look at this => http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html
You need to use deferredResult http://docs.spring.io/spring-framework/docs/3.2.0.BUILD-SNAPSHOT/api/org/springframework/web/context/request/async/DeferredResult.html
You will create a deferredResult object and you will return to the client. then asynchronously you will execute the logic and as soon as you finish you will inform the client that the request it´s done.
This technique is also know as "http long polling"
#RequestMapping("/")
#ResponseBody
public DeferredResult<String> square() throws JMSException {
final DeferredResult<String> deferredResult = new DeferredResult<>();
runInOtherThread(deferredResult);
return deferredResult;
}
private void runInOtherThread(DeferredResult<String> deferredResult) {
//seconds later in other thread...
deferredResult.setResult("HTTP response is: 42");
}

AsyncResponse ConnectionCallback does not fire in Jersey

For asynchronous programming, Jersey (JAX-RS) provides a ConnectionCallback callback that is to be executed when a connection is broken. From the Jersey docs:
As some async requests may take long time to process the client may
decide to terminate its connection to the server before the response
has been resumed or before it has been fully written to the client. To
deal with these use cases a ConnectionCallback can be used. This
callback will be executed only if the connection was prematurely
terminated or lost while the response is being written to the back
client. Note that this callback will not be invoked when a response is
written successfully and the client connection is closed as expected.
Sounds great, but I can never get this to fire.
Here's some code:
#GET
#Produces(MediaType.TEXT_PLAIN)
#ManagedAsync
#Path("/poll")
public void poll(#Suspended final AsyncResponse asyncResponse) {
asyncResponse.register(new CompletionCallback() {
#Override
public void onComplete(Throwable throwable) {
logger.info("onComplete called.");
}
});
asyncResponse.register(new ConnectionCallback() {
#Override
public void onDisconnect(AsyncResponse disconnected) {
logger.info("onDisconnect called.");
}
});
asyncResponse.setTimeout(POLL_TIMEOUT_SECONDS, TimeUnit.SECONDS);
asyncResponse.setTimeoutHandler(new TimeoutHandler() {
#Override
public void handleTimeout(AsyncResponse asyncResponse) {
logger.info("handleTimeout called.");
asyncResponse.resume(Response.status(Response.Status.OK).entity("TIMEOUT").build());
}
});
}
The other two callbacks shown, CompletionCallback and TimeoutHandler, fire just fine, without fail. If the specified timeout duration is reached, TimeoutHandler fires. If an AsyncResponse instance is resumed, CompletionCallback fires.
However, with ConnectionCallback, I can close, kill, or otherwise stop the client that is sitting connected to the web service shown above, and ConnectionCallback never gets fired.
Am I missing something? Is ConnectionCallback implemented in Jersey? (It's optional in the JAX-RS spec, but the Jersey docs talk about it as though it's implemented.)
Any input would be appreciated.
ConnectionCallback is indeed implemented in Jersey. And 'onDisconnect' callback is also invoked. You can take a look at the following code in Jersey:
https://github.com/jersey/jersey/blob/a6ff4d50da13d45ad90fd7375a15a31afa02e489/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java#L723
https://github.com/jersey/jersey/blob/b7907e279010e7035a7a3e529993d22f77a21e08/core-server/src/main/java/org/glassfish/jersey/server/ChunkedOutput.java#L246-L252
These are thrown in case of IOException while writing response. So, to answer your question, there is no polling or similar mechanism that keeps checking whether the client is connected, rather the onDisconnect method is called only when there is an IOException which usually occurs while writing response.
Update 1:
Also I would like to quote your own question:
"This callback will be executed only if the connection was prematurely
terminated or lost while the response is being written to the back
client"
So, unless you try to write to that stream, your callback will never be fired. To be clear, it's not meant to be called when there is no response to write or when the response is 202, rather it's meant to be invoked when the connection was terminated prematurely while response is being written.
I am afraid there is no workaround to this problem unless you write some low level network programming with polling of some sort. But I wouldn't recommend you to go for this.
I suggest that you rethink the way you want to handle this failure.

Waiting for an asynchronous call to complete first and then proceed in Java

I have a situation wherein I call a method which in turn triggers a asynchronous HTTP REST call(sends the status later to another endpoint) before it proceeds further. I want the method to wait until i get the response back to the endpoint, check the status i got and proceed further. I am looking for a feasible solution in Java. Any pseudo code or implementation will be helpful
saw similar case # Lightweight way of waiting for a group of asynchronous Java calls but not much idea about the same whether it is easy to implement.
Implementation details
I have JAX-RS endpoint to handle the async response as below
#POST
#Path("/status")
#Consumes("application/xml")
public Response processConfigStatus(#Context UriInfo uriInfo, ConfigStatus configStatus)
{
// process Status got from the async REST call
return ResponseHelper.createNoContentResponse();
}
Class which handles and processes
Class ProcessData{
public void updateData()
checktStatus(uri);
update();// should wait untill the processConfigStatus() endpoint gives status
}
private checktStatus(String uri){
// makes a REST call to a URI using a JAX-RS webclient or a httpclient this returns HTTP 200 or 204 code immediatley. And then the Server process the request asynchronously and gives back the status to JAX-RS endpoint(/status).
post(uri);
}
}
Method call from another Class
ProcessData pd = new ProcessData()
pd.updateData();
How about using a CountDownLatch?
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
Just as in the link you provided, you'll have to implement a way to simply keep track of how many async calls are stilling waiting for a response and wait until that count is zero.
count = numAsyncCalls
..calling all of the RESTful services here (each call must have some sort of callback to decrement 'count' variable above..
while (count > 0)
wait around
The use of the CountDownLatch in your link looks pretty much the same as my pseudo-code

Categories