Precondition for Camunda process in a REST application - java

In some cases when modeling a process with camunda one might have a precondition that has be to executed. If the precondition fails, the process instance should be stopped, returning an error event.
Now, the problem is that, once the process instance is started, you cannot return a mapped error code as an exception to the client who send the request, since an error can only be caugth with a listener.
public void createEntity(SomeEntity e) {
repository.save(e);
// start a workflow with camunda
startWorkflow(e);
/*
* If the precondition fails, it would be nice to throw an
* exception here, indicating 400 (Bad Request)
*/
}
If this is not possible, a simple solution would be to exclude that part from the workflow and only start it if the precondition is successful. But then, you cannot model the complete process with camunda, only a part of it. Returning 204 (No Content) and fetching the result of the process instance in a second query also seems wrong to me.
So, can you wait for a process instance to finish or at least return a mapped error code to the client within the request?

Related

MultipartHttpServletRequest is empty after first request

Since some days ago, my app started to have a very strange behavior on a spring boot #PostMapping request.
The code is as follows:
#PostMapping("/uploadFiles")
public ResponseEntity<Map<String,Object>> uploadFiles(MultipartHttpServletRequest request) throws IOException{
System.out.println(request.getParameterMap().keySet());
}
Pretty straigthfoward, nothing special here.
The problem is that the 'request' parameter only have parameters on the fist rest request the application receives. If other request is called before this, the request parameters will always be null. If the same request is sent twice to this endpoint, the fist one have all parameters / attached files, but the second is always empty.
Debugging the request parameter to identify what is going on, I identified the 'problem' occurs on 'MultipartStream.skipPreamble() (line 607 on 'tomcat-embed-core-9.0.27.jar'). When the method 'discardBodyData()' is called it is throwing the following exception, which make it never read the data from the stream:
org.apache.tomcat.util.http.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly
I have no idea what might be causing this. The toncat version wasn't updated (but its pretty old, I know), a new black project with this endpoint receive the parameter as many times as I pass it, other 'non-file' endpoints also receives the parameters and another colleague in the same project had the same problem (not a problem on my machine, it seems)
Any idea what might be causing this issue?

Spring : call REST API after receiving response from another REST API

I have a controller that calls a webservice to start a batch job, when the result is returned, it should call another REST API based on this result. Then it should wait for the new result, and return this second result to user:
#RestController
public class LaunchController {
#PostMapping(path = "/launch", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<LaunchResult> launch(#Valid #RequestBody LaunchParams params) {
// in launch() I call the first REST API
LaunchResult result = myService.launch(params);
// here I need to call another REST API
AnotherResult result2 = callAnotherWebAPIBasedOnThisResult(result);
return ResponseEntity.ok(result2);
}
Now I want to know that is it good practice to do it like this (synchronously) and all in one controller ? Exist other way of doing this ?
Your controller is perfectly fine as it does not have any application logic inside and it actually calls the service methods. But It lacks the exception handling. You have catch with proper exceptions with try catch block or throws keyword.
The decision to convert the endpoint to an asychronous one depends on a few factors :
Is the batch job going to take time to be executed.
Can this process be converted to an asynchronous one.
Does the use case expect the user to wait until the action is completed.
If the your answer is yes, it's better to convert the endpoint to an ayschronous one and update the user with the details later after all processes including the batch processes are completed . It's always better NOT to keep the user waiting for a response. Non-blocking requests makes sense when you are dealing with a lot of data and processing needed for this data. Also, by making this request asynchronous you will have better control over the processing stages and provide the user with better statistics incase any of the processing stage resulted in failure. For instance the batch job could fail or the second rest api call could result in an error.

jersey ws 2.0 #suspended AsyncResponse, what does it do?

I am analyzing some jersey 2.0 code and i have a question on how the following method works:
#Stateless
#Path("/mycoolstuff")
public class MyEjbResource {
…
#GET
#Asynchronous //does this mean the method executes on child thread ?
public void longRunningOperation(#Suspended AsyncResponse ar) {
final String result = executeLongRunningOperation();
ar.resume(result);
}
private String executeLongRunningOperation() { … }
}
Lets say im at a web browser and i type in www.mysite/mycoolstuff
this will execute the method but im not understanding what the asyncResponse is used for neither the #Asynchronous annotation. From the browser how would i notice its asychnronous ? what would be the difference in removing the annotation ? Also the suspended annotation after reading the documentation i'm not clear its purpose.
is the #Asynchronous annotation simply telling the program to execute this method on a new thread ? is it a convenience method for doing "new Thread(.....)" ?
Update: this annotation relieves the server of hanging onto the request processing thread. Throughput can be better. Anyway from the official docs:
Request processing on the server works by default in a synchronous processing mode, which means that a client connection of a request is processed in a single I/O container thread. Once the thread processing the request returns to the I/O container, the container can safely assume that the request processing is finished and that the client connection can be safely released including all the resources associated with the connection. This model is typically sufficient for processing of requests for which the processing resource method execution takes a relatively short time. However, in cases where a resource method execution is known to take a long time to compute the result, server-side asynchronous processing model should be used. In this model, the association between a request processing thread and client connection is broken. I/O container that handles incoming request may no longer assume that a client connection can be safely closed when a request processing thread returns. Instead a facility for explicitly suspending, resuming and closing client connections needs to be exposed. Note that the use of server-side asynchronous processing model will not improve the request processing time perceived by the client. It will however increase the throughput of the server, by releasing the initial request processing thread back to the I/O container while the request may still be waiting in a queue for processing or the processing may still be running on another dedicated thread. The released I/O container thread can be used to accept and process new incoming request connections.
#Suspended have more definite if you used it, else it will not make any difference of using it.
Let's talk about benefits of it:
#Suspended will pause/Suspend the current thread until it gets response,by default #NO_TIMEOUT no suspend timeout set. So it doesn't mean your request response (I/O)thread will get free and be available for other request.
Now Assume you want your service to be a response with some specific time, but the method you are calling from resource not guarantee the response time, then how will you manage your service response time? At that time, you can set suspend timeout for your service using #Suspended, and even provide a fall back response when time get exceed.
Below is some sample of code for setting suspend/pause timeout
public void longRunningOperation(#Suspended AsyncResponse ar) {
ar.setTimeoutHandler(customHandler);
ar.setTimeout(10, TimeUnit.SECONDS);
final String result = executeLongRunningOperation();
ar.resume(result);
}
for more details refer this
The #Suspended annotation is added before an AsyncResponse parameter on the resource method to tell the underlying web server not to expect this thread to return a response for the remote caller:
#POST
public void asyncPost(#Suspended final AsyncResponse ar, ... <args>) {
someAsyncMethodInYourServer(<args>, new AsyncMethodCallback() {
#Override
void completed(<results>) {
ar.complete(Response.ok(<results>).build());
}
#Override
void failed(Throwable t) {
ar.failed(t);
}
}
}
Rather, the AsyncResponse object is used by the thread that calls completed or failed on the callback object to return an 'ok' or throw an error to the client.
Consider using such asynchronous resources in conjunction with an async jersey client. If you're trying to implement a ReST service that exposes a fundamentally async api, these patterns allow you to project the async api through the ReST interface.
We don't create async interfaces because we have a process that takes a long time (minutes or hours) to run, but rather because we don't want our threads to ever sleep - we send the request and register a callback handler to be called later when the result is ready - from milliseconds to seconds later - in a synchronous interface, the calling thread would be sleeping during that time, rather than doing something useful. One of the fastest web servers ever written is single threaded and completely asynchronous. That thread never sleeps, and because there is only one thread, there's no context switching going on under the covers (at least within that process).
The #suspend annotation makes the caller actually wait until your done work. Lets say you have a lot of work to do on another thread. when you use jersey #suspend the caller just sits there and waits (so on a web browser they just see a spinner) until your AsyncResponse object returns data to it.
Imagine you had a really long operation you had to do and you want to do it on another thread (or multiple threads). Now we can have the user wait until we are done. Don't forget in jersey you'll need to add the " true" right in the jersey servlet definition in web.xml to get it to work.

Spring Controller start processing after response is sent

I am using a Spring MVC controller and want to start the execution of a task in a new thread. However the task should not start immediately but only after the response has been sent to the client.
The sequence - in strict temporal order:
request
return new ResponseEntity ... / client receives HTTP status 200 OK.
processing of the task begins.
How do I achieve this?
I wanted to use Spring's async abstraction by calling a method annotated with #Async, but it does not guarantee that the new thread waits for the response to be sent first.
You can use an interceptor for that. The order of events for handling a request in Spring MVC is:
DispatcherServlet get a Request, Response pair and determines the handling
[optional] interceptors preHandle are called (with option to stop processing)
controller is called
[optional] interceptors postHandle are called
ViewResolver and view do the actual Response processing and send the response
[optional] interceptors afterCompletion are called
The above is over simplified and is just aimed at showing that interceptor afterCompletion methods are called after the response has been sent to client, with following signature :
void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex)
throws Exception
In that method, you can test the occurence of an exception and the correctness of the response (ex == null && response.getStatus() == HttpServletResponse.SC_OK) before starting your processing.
The HandlerInterceptor is the solution, but the code get a little bit more complex than expected.
Here's a code suggestion to make it simpler by putting the whole solution in a single class:
private static final ThreadLocal<Object> result = new ThreadLocal<Object>();
#RequestMapping("/mypath")
public Object execute() throws Exception {
Object obj = new Object();
result.set(obj); // Save the object to be used after response
return obj;
}
#Bean
public MappedInterceptor interceptor() {
return new MappedInterceptor(Arrays.array("/mypath"), new HandlerInterceptor() {
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// Get the saved object
Object results = result.get();
// Clean for the next request
result.set(null);
// TODO Your code to be executed after response.
}
});
}
If your "after respond is sent" requirement is fulfilled with "after the view has been rendered" you may use an implementation of HandlerInterceptor. For an example cf. Spring 3 MVC Interceptor tutorial with example, triggering your job in afterCompletion.
If your job needs to be triggered "after it hit the wire", I'd like to know why.
You could add the task to a blocking queue, before the response entity is created. Let a task executor run periodically (every x seconds) over the queue and poll for tasks. If a task is found, it will be executed. If not, the thread finishes its run method and waits for the next run (in x seconds).
How to run a task periodically:
http://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/
Inject the queue as dependency in both the controller and the task executor service. This should be an easy solution to start with.
In this szenario you can't be sure, that the client receives the request. But if you want to be safe(r), add a due date to your task object with a sufficient offset (e.g. current time + 30 seconds). Let the task executor check if the due date of the polled task is now or in the past. Otherwise ignore the task for this run.

Spring #Transaction annotation and Exception Handling

Consider the following code snippet. (I am using Spring 3.1 and Hibernate 3.6)
#Override
#Transactional
public <T extends Termination> void progressToPendingStage(Class<T> entity,
Long terminationId, String userName) throws Exception {
Termination termination = findTerminationById(entity, terminationId);
//TODO improvise such that email does not get sent if data is not saved
if (termination.getStatus().equals(TerminationStatus.BEING_PREPARED.toString())) {
termination.setStatus(TerminationStatus.PENDING.toString());
termination.setSubmittedDate(new Date());
termination.setSubmittedBy(userName);
saveOrUpdateTermination(termination);
//Send an email to SAS
emailHelper.configureEmailAndSend(termination);
}
}
Unit tests for the above method indicate that email will be sent regardless that the saveOrUpdateTermination(termination) throws an exception or not. On further testing and some research I have uncovered that this behavior is the expected behavior. This is not what the business rules desire. An email should be sent only if the termination record was saved successfully. Any suggestions on how to make this behave in the desired manner? One way I can think of is to make the caller handle the exception thrown by the progressToPendingStage method and if no exception was thrown send an email. Am I on the right track or can we alter the way #Transaction behaves.
I have solved this issue by designing around the problem. Sending an Email was never meant to be part of the transaction. I created an object that performed post saving tasks. The object will catch the exception thrown upon saving the termination and if no exceptions were thrown I would then trigger an email to be sent out. One could also put this in an Spring Aspect which could be executed upon successfully returning after a successful save.
Lessons learn't: Don't include steps that don't belong in a method marked with #transaction. If its included in a transaction Spring will silently handle the exception and not throw the exception till the transaction is finished. In short if a method is annotated with #Transaction every line in that method will be execute even though a line in the middle of the method throws an exception.

Categories

Resources