RestService Response from Process

Hi All,
I am a beginner, I am trying to invoke the process using a REST call, execute some processes(call external Rest service, execute some business logic) and respond back to REST call with the output from the processes.
Could you refer me to any examples?
I am following this example

The missing part is, how do I respond back to REST call with outcome from the processes.

Hi @BerndRuecker, Could you help me with this?

Hi camundacast.

Question: Do you only want to invoke synchronous rrequests in your process or will it be asynchronous (as shown in the linked example where AMQP is used)?

Cheers
Bernd

Hi @BerndRuecker,
Thanks for the response, There will be synchronous and asynchronous processes.

Thanks,
camundacast

In this case you have to wait until the process instance completes in the REST service which started the process instance. You could either do some polling or notify you back by some in-memory queue or callback. I know that I have sample code showing this, but I didn’t find it spontaneously. Pseudo-Code out of my head, might recall it not completely right - but might be a good starting point:

public static Map<String, BlockingQueue> queues;

myRestCall() {
  var pi = camunda.startProcessInstanceByKey(); 
  var queue = new BlockingQueue();
  queues.put(pi.getId(), queue);
  var  x = queue.poll( 3, SECONDS);
  if (x!=null) {
    // process instance finished :slight_smile:
   return xxx; 
  } else {
    // not yet done - what to do?
  }
}

And then you can add a listener:

NotifyListener implements ExecutionListener {
  public voud execute()  {
    Client.queues.get(pi.getId()).put("yeah - here you can transfer some result")
  }
}

Hi @BerndRuecker,
Thanks for the code, I am specifically looking for a way to capture the output from a process in the rest call, Lets assume all the synchronous processes.

@RequestMapping(method=RequestMethod.POST)
  public OrderResponse placeOrderPOST(String orderId, int amount) throws Exception	{
	  ProcessInstance instance =  camunda.getRuntimeService().startProcessInstanceByKey(//
		        ProcessConstants.PROCESS_KEY_order, //
		        Variables //
		          .putValue(ProcessConstants.VAR_NAME_orderId, orderId) //
		          .putValue(ProcessConstants.VAR_NAME_amount, amount));
	  OrderResponse response = new OrderResponse();
	  // How do I retrieve the response of the completed processes??
	  
	  return response;
	  
  }

Thanks.

Yes, I understood this. The problem is, that when the startProcessInstanceByKey method returns, the process instance might not yet be ended (due to asynchronous processing).

So as a next thing you have to either poll the engine to query when the process instance ends (e.g. via the HistoryService) and then load some process variables from it (again, e.g via the HistoryService).

And if you want to avoid the polling you need some in-memory way to notify the waiting thread that a process instance ends.

makes sense?

@BerndRuecker I got it, I will poll from REST Service which started the process Instance, once the polling resulted in a completed process(external REST call), how do I get the results of REST call inside the REST service which started the process instance?
Sorry for lot of questions.

You can also polol within Java:

@RequestMapping(method=RequestMethod.POST)
  public OrderResponse placeOrderPOST(String orderId, int amount) throws Exception	{
	  ProcessInstance instance =  camunda.getRuntimeService().startProcessInstanceByKey(//...

	  OrderResponse response = new OrderResponse();

      for {
        // query - and if count > 0 then use it to read variables
        camunda.getHistoryService().createProcessInstanceQuery().endedI()...
       }
	  
	  return response;

Hi @BerndRuecker, Thanks, I was able to retrieve the variable information using historyService.

Just for the record, I can now point you to a working code example for what I had in mind:

https://github.com/flowing/flowing-retail/blob/master/payment/src/main/java/io/flowing/retail/payment/port/rest/PaymentRestController.java#L32

and

https://github.com/flowing/flowing-retail/blob/master/payment/src/main/java/io/flowing/retail/payment/port/rest/NotifySemaphorAdapter.java

This is not yet production ready code - but pretty close to what I would do. You just have to make sure, that the camunda transaction is already committed when you release the semaphore (I solved this by making the end event asyncBefore=true).

1 Like

Couldn’t we just use the createProcessInstanceByKey(processDefinitionKey).businessKey(businessKey).setVariables(variables).executeWithVariablesInReturn() in this case? That is if one wants to execute the process end get variables on finish. That is if process execute in one transaction.

1 Like

If you have synchronous processes that might be an option. The case we discussed was processes, that are asynchronous or at potentially long running, e.g. because some service might not be available and you want to do retrying or you wait for some result as message.

@BerndRuecker @mresetar Thanks so much for the responses, This is really helpful.

Do we have any updated approch for sendind the response from process to rest api or below code is enough ?

@RequestMapping(method=RequestMethod.POST)
public OrderResponse placeOrderPOST(String orderId, int amount) throws Exception {
ProcessInstance instance = camunda.getRuntimeService().startProcessInstanceByKey(//…

  OrderResponse response = new OrderResponse();

  for {
    // query - and if count > 0 then use it to read variables
    camunda.getHistoryService().createProcessInstanceQuery().endedI()...
   }
  
  return response;

I am also looking for same solution on async process. These links are not working. Can you share the correct one.

The code did move a bit - the semaphore variant is here: https://github.com/berndruecker/flowing-retail/blob/master/rest/java/payment-camunda/src/main/java/io/flowing/retail/payment/resthacks/PaymentRestHacksControllerV4.java#L84

This Helps. Thank You so Much !!!

Hi, I’m a bit lost in this example : after kicking of the process by calling the PUT /payment/v5 API, if I want to retrieve the current process status, do I just need to call the same service with the same inputs ? the problem with this is each time I call this service Camunda spawn a new process, and I always get “pending” as a response.
I’ve also tried to make add another API to get the current status by providing the same initial input + the traceId, but again, Camunda spawn a new process.
Thanks for your clarification.

Hi, I have a question please regarding these code examples : if we want to wait for the hole process to finish, do we have to use acquire() method instead of tryAcquire() ? because tryAcquire will always return false as a first try, and then we will always get the pending status.

Hi Abdessamad.

Thanks for your question. I am happy that you try out the code and get to the right essence :slight_smile:

For the query method: It is simply not implemented in this example, but I agree that there should be a possibility to query the status. I briefly went ahead and implemented it here: https://github.com/berndruecker/flowing-retail/blob/master/rest/java/payment-camunda/src/main/java/io/flowing/retail/payment/resthacks/PaymentRestHacksControllerV5.java#L66

I also agree that calling the put method again should probably not be processed so the whole operation is idempotent. If you want to provide a pull request for that I will be more than happy to apply it!

I haven’t yet fully understand what the problem of the “tryAcquire” is exactly. It should try to acquire the lock for the timeout max - which is exactly what I want - no?

Best
Bernd