2

I have below code which formats the files from one form to another. Process takes some time so we have wait time of 5 mins in case file takes time to process we destroy it.

The application flow is a http call is made from browser which hits spring boot @Controller class and lastly executes below code which is into @Service class of springboot application.

On load test I see in task manager many formatter.exe present even after springboot application is closed. My question is it correct way to implement in multi user concurrent environment. Also can some help me how can I increase performance executing "exe" when multiple request are made simultaneously

process = Runtime.getRuntime().exec(runtime.exec("c:\\modifier\\formatter.exe"););

if (!process.waitFor(5, TimeUnit.MINUTES)) {
  process.destroyForcibly();
  process = null;
}
M. Deinum
  • 115,695
  • 22
  • 220
  • 224
user593029
  • 511
  • 7
  • 18

1 Answers1

2

This is not a good practice to wait for http request to complete in 5 minutes as well as waiting for separate process to complete. I assume, your endpoint is synchronized (not async request mapping) since you have not provided mapping details.

If you start a separate process and until you explicitly shutdown or kill it, that certain process will be running (if that process hanged). Refer this question to get an understand how to terminate a process and refer this document as well.

As I said, keeping a http request waiting for 5 minutes is not a good practice. I suggest a different approach for this solution as you use Spring Boot. You can simply make your endpoint asynchronous using @Async annotation for not to wait the request till process to complete. (How To Do @Async in Spring is a good document to see in this case)

Now you can change the controller implementation to use a message broker (RabbitMQ, ActiveMQ, JMS and so forth) queue requests and immediately respond back to the client (Messaging with RabbitMQ). So, your client (browser) see the response immediately even without process is started. You can handle the response at client side as you want then.

Now you can write a different program to dequeue messages from the broker and start the separate process. It doesn't matter how long that process takes as we have already given the response to the client and you don't need to destroy the process until that process is completed (if it hanged, just kill the process and re-queue message to the queue. This way we can ensure that every request will be processed).

After the process is done, you can notify the client by a push notification or Websocket implementation with resulted data.

I know this could be overdoing a simple task. But if you want to keep your feature's reliability and usability, this is worth doing. Also, you can use this in Microservice architecture. In fact this is a concept of Microserivces. Here is a good read to learn some about this approach.

Sachith Dickwella
  • 1,388
  • 2
  • 14
  • 22
  • Sachith, one question the link stack link that you provided do we really require to use " p.waitFor()" when we use t.schedule(killer, 30000);. I think schedule will take care & p.waitFor() seems to be redundant https://stackoverflow.com/questions/14483397/how-to-exit-a-process-exec-if-the-external-program-hangs – user593029 May 16 '19 at 13:16
  • Yeah, `p.waitFor()` function will keep your application's worker thread waiting till external process to be terminated **externally**. That implies, it could keep your worker thread on hold indefinitely until you done your work with the external-process. If the external process terminate itself after the process is done, this would be the proper function to use rather than a killing it after a fix time, because processing time of each process could be vary. But in your case, if your process won't terminate itself sometime, better go with the `t.schedule(killer, 30000)` than the other. – Sachith Dickwella May 17 '19 at 02:36