How to receive a response back from a foreign API in an event handler

Hello @Andriy_Konoz
[I reposted this as a new, separate topic]

I didn’t mark this as “Answered” yet, because it wasn’t. Sergey did :slight_smile:

I think that you are misunderstanding the question.
This is what I need to do.

  • After the database afterCreate event I need to POST a call to a foreign API.

  • After the POST call is made from the event handler, I need to receive the response back from the call for further processing

The problem is Sergey told me to put it into an async block for it to work properly, but I’m unable to get the response because I’m guessing that it’s going out of scope before I can retrieve the response from the foreign API.

How can this be done so I can capture the response back from the foreign API?

Mike

Hello @Michael_Kadron,

Sorry for the misunderstanding. I’ve read through your topic and have a suggestion to help you achieve the desired result.

First, I assume that you’re creating orders exclusively via API Service methods and not directly saving them into the database from the client side. This means the process of saving an order always goes through this codeless logic—am I correct?

If that’s the case, you don’t need an afterCreate event handler to perform operations after creating a new record in the database. This also applies to the afterUpdate case. The afterCreate handler is typically used when you need to modify the response after object creation or when you need to run logic after creation if it can happen from multiple different places. Since your creation process is centralized, you can run any logic (e.g., sending an HTTP request to a third-party service and logging the response) right after the Save Object in Backendless block. The main point is you don’t need the afterCreate event handler if you want to perform any logic after object creation, you may perform it right after the creation logic and it will work.

For clarity, you might want to move this logic into a custom function and call it right after the Save Object in Backendless block. How does that sound to you?

Regards,
Stanislaw

Hello @stanislaw.grin

No, actually the reason why I’m using the database afterCreate event is because several, different Backendless API services will be creating new records in this particular table and I need to respond to each afterCreate event.

That’s why I wanted to do it this way.

Let me restate the process again:

#1: A new record is created in this particular table from an internal API call

#2: I respond to this event in the afterCreate event handler for this table

#3: I take the data object from the afterCreate handler and I do a POST call to a foreign API (using the async block as Sergey (Kuk) recommended. When I didn’t use this block before, I only get an “The object has moved here” “error” in the RT Logs when this should have been happening.)

#4: I need to get the response from the foreign API back! This is what I’m asking on how to do from using the async block. It appears that the call is going out of scope before the variable can even be set with the response! How can this be done???

#5: After I get the response back, I need to do some further local processing. (No big deal)

Somehow, I need to get the response back from the foreign API call (in the async block).

That’s my question.

Mike

Hello @Michael_Kadron,

Thanks for the clarification! I have a few more questions:

  1. Can we reproduce this issue? Could you create a test handler with minimal reproducible code for debugging purposes?
  2. Is the afterUpdate handler currently working correctly? I’ve checked the logs and noticed a response from the foreign API.
  3. When was the last invocation of the afterCreate handler with the current logic? We’d like to review the logs from that time to understand what was happening.
  4. Have you tried wrapping the HTTP request to the foreign API in a Try/Catch block and logging any errors? Based on the current logic in the afterCreate handler, if the foreign API request fails, it could prevent further logs and logic from executing unless there’s a catch block to handle the error.

Regards,
Stanislaw

Hello again @stanislaw.grin

Yes, the afterUpdate handler is working correctly – I’ve not had any issues with this one, but maybe that’s because this action is being triggered by a Make Scenario that’s polling in the background periodically.

The last invocations of the afterCreate handler were:
(Actually, I’ve never seen any evidence that the afterCreated event handler has ever actually been called)

Trigger: LabSavvy API /create – trying the POST call to the foreign API from this API route
Log:

Wed Aug 21 2024 15:13:43 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] Building ServerCode Model for path (/opt/backendless/repo/51d297f6-92e1-171f-ff15-a7a602959f00/files/servercode/CODELESS/LabSavvy/PRODUCTION)
Wed Aug 21 2024 15:13:43 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] ServerCode Model built in 32ms
Wed Aug 21 2024 15:13:43 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] [D14DA93B-8901-4FBE-B691-667A861F811E] [INVOKE SERVICE] services.LabSavvy.Create_Order
Wed Aug 21 2024 15:13:44 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] {"starred":1,"date":"2024-08-21T19:13:44.272Z","number":"LS000-BILT-TEST-CASE0","billing":{"company":"LabSavvy","contact":"LabSavvy","addressName":"LabSavvy","addressType":"LabSavvy","address":{"line1":"1234 Anywhere Street","line2":"","city":"Boonies","stateProvince":"GA","postalCode":"39851","country":"USA"}},"shipping":{"company":"LabSavvy","contact":"LabSavvy","addressName":"LabSavvy","addressType":"LabSavvy","address":{"line1":"1234 Anywhere Street","line2":"","city":"Boonies","stateProvince":"GA","postalCode":"39851","country":"USA"}},"lines":{"lineNumber":1,"item":{"id":585,"name":"1-BILT Test Product"}},"customer":{"id":"684","name":"LabSavvy"}}
Wed Aug 21 2024 15:13:44 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] ### INSIDE FUNCTION ###
Wed Aug 21 2024 15:13:44 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] undefined
Wed Aug 21 2024 15:13:44 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] #######################
Wed Aug 21 2024 15:13:44 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] ################################################### SOS RESPONSE ###################################################
Wed Aug 21 2024 15:13:44 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] undefined
Wed Aug 21 2024 15:13:44 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] ################################################### SOS RESPONSE ###################################################
Wed Aug 21 2024 15:13:44 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412062] Processing finished in 1084.007ms

Trigger: SOSOrder/Create API Action – trying the POST call to the foreign API in this route
Log:

Wed Aug 21 2024 15:15:09 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] Building ServerCode Model for path (/opt/backendless/repo/51d297f6-92e1-171f-ff15-a7a602959f00/files/servercode/CODELESS/SOSAPI/PRODUCTION)
Wed Aug 21 2024 15:15:09 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] ServerCode Model built in 36ms
Wed Aug 21 2024 15:15:09 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] [A765FB4B-40AD-4A30-9BB1-49BC5ECF1624] [INVOKE SERVICE] services.SOSAPI.SOSOrder
Wed Aug 21 2024 15:15:09 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] { dataObject: { starred: 1, date: '2024-08-17T09:00:00', number: 'LS999-BILT-TEST-CASE9', channel: { name: 'LabSavvy' }, billing: { company: 'LabSavvy', contact: 'LabSavvy', phone: null, email: null, addressName: '', addressType: '', address: [Object] }, shipping: { company: 'LabSavvy', contact: 'Beth-6 to BILT Oteyza', phone: null, email: null, addressName: '', addressType: '', address: [Object] }, lines: [ [Object] ], customer: { id: 684, name: 'LabSavvy' } }, starred: 1, number: 'string', channel: { name: 'LabSavvy' }, billing: 'string', shipping: 'string', lines: [ { id: 4948, lineNumber: 1, item: [Object], class: [Object], job: null, workcenter: null, tax: [Object], linkedTransaction: null, description: 'item used to test BILT workflows', quantity: 1, weight: 0, volume: 0, weightunit: 'lb', volumeunit: 'cbm', unitprice: 0, amount: 0, altAmount: 0, picked: 0, shipped: 1, invoiced: 0, produced: 0, returned: 0, cost: 0, margin: 0, listPrice: null, percentdiscount: null, backOrdered: 0, duedate: '2024-08-06T00:00:00', uom: null, bin: null, lot: null, serials: null } ], customer: { id: 684, name: 'LabSavvy' } }
Wed Aug 21 2024 15:15:09 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] LabSavvy
Wed Aug 21 2024 15:15:09 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] We have a valid dataObject!!! -- Using passed dataObject as the database source.
Wed Aug 21 2024 15:15:10 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] ################ POSTING TO SOS ################
Wed Aug 21 2024 15:15:10 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] ######## RESPONSE FROM SOS ########
Wed Aug 21 2024 15:15:10 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] undefined
Wed Aug 21 2024 15:15:10 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] ###################################
Wed Aug 21 2024 15:15:10 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [2412744] Processing finished in 674.214ms

I’m not currently getting any actions that are inside the onCreate event handler, but I’m not sure why it’s not being triggered. Is it possible to run a cURL POST command from the Node JS backend? Can something like fetch be run?

Yes, I had previously tried the Try…Catch…Finally block – but I couldn’t get it working with this either.

I’m currently working on a minimal reproducible example…

Mike

Hello @Michael_Kadron,

How does Make Scenario make an HTTP request to the Backendless API? What API Key does it use?
It seems that it still uses the Cloud Code API Key, which, as was stated in this post, will not trigger event handlers.
Could you please check what API Key does Make use to invoke Backendless API?

Stanislaw

I think I understand the scenario and where things might not be working as expected.

Let me clarify—when you expect the event handler to trigger, is the request going to the Create Order method (which in turn saves the object to the table) or directly to the table? If I understand correctly, it doesn’t work when the request goes through the Create Order method (even though you might be using a different API Key from the Cloud Code API Key for the request). If that’s the case, I know why the handler isn’t triggering in this situation.

The issue is that even though you’re accessing the API Service using a non-Cloud Code API Key, any calls made from within your API method logic will still use the Cloud Code API Key. Therefore, saving an object to the table from inside the API Service won’t trigger the event handler. To trigger it from within the API Service, you need to use the HTTP Request block instead of the Save Object In Backendless block, and make the same request to save the object to the table using the REST API, specifying a non-Cloud-Code API Key.

Hello @stanislaw.grin

I said the one that was WORKING was using the Make Scenario:

…and no, I’m not using the ServerCode API Key, I created a separate API key specifically for Make to use.

The API service that’s not working correctly is a local API that’s saving a record to a database – this action (which is a Save an Object in Backendless Block) is NOT triggering the afterCreate event handler in the database.

That’s why I asked you if it was possible to send a cURL POST from a Backendless API Service.

Is it possible?

Won’t this trigger the afterCreate event handler properly?

Do you have any examples for doing this in Backendless along with getting the response back from the cURL request?

Thank you for your help.

Mike

Here is an example of saving object to DB with a HTTP request (not using Save an Object block):

image

The path value should be as follows:

https://api.backendless.com/:app-id/:api-key/data/:table-name

substitute your values to the app-id, api-key, and table-name.

Here is the documentation for this API route:
https://backendless.com/docs/rest/data_single_object_create.html

Hope it helps.

Regards,
Stanislaw

Hello @stanislaw.grin

Yes, I know how to do a HTTPs request call, thank you :slight_smile:

Let me ask this again for clarification:

To recap, Sergey (Kuk) has me place the existing HTTPs call to the foreign API inside an async block because I was only getting an error (Something like: “Object moved to here” and “here” was a link to: Backendless)

I need to get the response back from the foreign API POST call.
But it’s in a async block :slight_smile:

Mike

Hello @Michael_Kadron,

Yes, I know how to do a HTTPs request call, thank you

You asked:

That’s why I asked you if it was possible to send a cURL POST from a Backendless API Service.

I described to you how to do it. The only difference is that it is an HTTP request, not a cURL, but why would you need a cURL? The HTTP block will do the same thing. So I just answered your question.

Sergey (Kuk) has me place the existing HTTPs call to the foreign API inside an async block

Sergey gave you the wrong suggestion due to a misunderstanding (I apologize for that), but later on that topic @vladimir-upirov described why this (an async block) will not work in your case and why you should not use it. There’s no way to get a response in an async block, the reason is described here:

I tried to solve your issue without async block and, if I reproduce your logic in my demo app, it will work as you expect. Have you tried what I have suggested?

Regards,
Stanislaw

Hello @stanislaw.grin

If you look at the orginal post for this issue, (Andriy has me create a new topic) this is the very first thing that I tried. I had already tried using the HTTPs request block for doing the API Call to the Foreign API and I get this response back:

Here is the snippet:

So in summary, this was the first thing that I tried that didn’t work, which is why I created the support topic to begin with: :slight_smile:
Link to original post

It returned the “error” that I quoted above.

Putting this in an async blocked prevented the error, but also prevents me from getting the response back from the foreign API. Here it is with the async block removed:

I get that this won’t work in an async block (because you can’t capture the response), it also won’t work OUTSIDE of the async block!!! :slight_smile:

I’m going to resume working on the minimal example for you later today to look at because an AppID is worth a thousand words :smiley:

Mike

Hi @Michael_Kadron ,
I saw that your methods have changed a little and you have created a separate API service - APISOS.

  1. If you want the afterCreate handler to be called after adding data to the database, you must save data to the database using an http request (as I showed on the screenshot)

  2. Schematically, I provided an example of logic that you can use in your application. In this case, both variables will be available within this method.

  3. If an error occurs and you are transferred to the catch block, then you need to localize the problem, check the request which request causes the error. If an error occurs in an external api call, then try to make a successful request to this api using curl, if everything works out with curl, we can help you correctly transfer the curl request to codeless blocks.

If something does not work, we will be happy to help.

Best regards,
Sergey

Hello @Sergey_Androsov

That’s where I’m having the problem.

I’m working within the SOSAPI/SOSOrder route. (Look within the Try…Catch…Finally block)

I’m trying to make a POST to an external API and catch the response in the SOSResponse variable like this: (This is not the actual code block)

When I try this API call, I get the following errors:

Thu Aug 29 2024 16:27:45 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] Building ServerCode Model for path (/opt/backendless/repo/51d297f6-92e1-171f-ff15-a7a602959f00/files/servercode/CODELESS/SOSAPI/PRODUCTION)
Thu Aug 29 2024 16:27:45 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] ServerCode Model built in 30ms
Thu Aug 29 2024 16:27:45 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] [BF039A90-961D-4C24-859E-DB513DA0669A] [INVOKE SERVICE] services.SOSAPI.SOSOrder
Thu Aug 29 2024 16:27:45 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] { dataObject: { starred: 1, date: '{{current_timestamp}}', number: 'LS104-BILT-TEST-CASE4', channel: { name: 'LabSavvy' }, billing: { company: 'LabSavvy', contact: 'LabSavvy', phone: null, email: null, addressName: '', addressType: '', address: [Object] }, shipping: { company: 'LabSavvy', contact: 'Beth-6 to BILT Oteyza', phone: null, email: null, addressName: '', addressType: '', address: [Object] }, lines: [ [Object] ], customer: { id: 684, name: 'LabSavvy' } }, starred: 1, number: 'string', channel: { name: 'LabSavvy' }, billing: 'string', shipping: 'string', lines: [ { id: 4948, lineNumber: 1, item: [Object], class: [Object], job: null, workcenter: null, tax: [Object], linkedTransaction: null, description: 'item used to test BILT workflows', quantity: 1, weight: 0, volume: 0, weightunit: 'lb', volumeunit: 'cbm', unitprice: 0, amount: 0, altAmount: 0, picked: 0, shipped: 1, invoiced: 0, produced: 0, returned: 0, cost: 0, margin: 0, listPrice: null, percentdiscount: null, backOrdered: 0, duedate: '2024-08-06T00:00:00', uom: null, bin: null, lot: null, serials: null } ], customer: { id: 684, name: 'LabSavvy' } }
Thu Aug 29 2024 16:27:45 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] LabSavvy
Thu Aug 29 2024 16:27:45 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] We have a valid dataObject!!! -- Using passed dataObject as the database source.
Thu Aug 29 2024 16:27:46 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] ################ POSTING TO SOS ################
Thu Aug 29 2024 16:27:46 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] ResponseError:
Object moved to here.
at checkStatus (/usr/local/lib/node_modules/backendless-coderunner/node_modules/backendless-request/lib/request.js:343:9) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { code: undefined, status: 302, headers: { connection: 'close', 'content-type': 'text/html; charset=utf-8', date: 'Thu, 29 Aug 2024 20:27:46 GMT', server: 'Microsoft-IIS/10.0', 'cache-control': 'private', location: '/error.aspx?status=HYbB5vm9hJPmFvTGq3cdGjfzxNqYhDqwsANSPNpHdw9JThVINObXDQ%3d%3d', 'set-cookie': [ 'ASP.NET_SessionId=va11msojhx4tcvld5u0wp3un; path=/; secure; HttpOnly; SameSite=Lax' ], 'transfer-encoding': 'chunked', p3p: 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"', 'x-aspnetmvc-version': '5.0', 'x-aspnet-version': '4.0.30319', 'request-context': 'appId=cid-v1:e74c2273-dd32-44f9-8e8a-32064c6b854d', 'x-powered-by': 'ASP.NET', 'x-frame-options': 'ALLOW-FROM https://saddleoak.fogbugz.com' }, body: '\r\n' + '
Object moved to here.
\r\n' + '\r\n' }
Thu Aug 29 2024 16:27:46 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] ######## RESPONSE FROM SOS ########
Thu Aug 29 2024 16:27:46 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] undefined
Thu Aug 29 2024 16:27:46 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] ###################################
Thu Aug 29 2024 16:27:46 GMT-0400 (Eastern Daylight Time) | SERVER_CODE | INFO | [349336] Processing finished in 1290.031ms

and the variable SOSResponse is undefined.

Yes, the call to the external API is working correctly from Postman.

Again, (for convenience) the AppID is: 51D297F6-92E1-171F-FF15-A7A602959F00
Services/SOSAPI/SOSOrder route. (Look within the Try…Catch…Finally block)

Mike

Hi @Michael_Kadron,

The error you’re seeing is due to the response from api.sosinventory.com. Their API is returning an HTTP 302 status code, which redirects to an error page (see their response below):

{
  "status": 302,
  "headers": {
    "connection": "close",
    "content-type": "text/html; charset=utf-8",
    "date": "Thu, 29 Aug 2024 20:27:46 GMT",
    "server": "Microsoft-IIS/10.0",
    "cache-control": "private",
    "location": "/error.aspx?status=HYbB5vm9hJPmFvTGq3cdGjfzxNqYhDqwsANSPNpHdw9JThVINObXDQ%3d%3d",
    "set-cookie": [
      "ASP.NET_SessionId=va11msx4tcvld5u0wp3un; path=/; secure; HttpOnly; SameSite=Lax"
    ],
    "p3p": "CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"",
    "x-aspnetmvc-version": "5.0",
    "x-aspnet-version": "4.0.30319",
    "request-context": "appId=cid-v1:e74c2273-dd32-44f9-8e8a-32064c6b854d",
    "x-powered-by": "ASP.NET",
    "x-frame-options": "ALLOW-FROM https://saddleoak.fogbugz.com"
  },
  "body": "\r\nObject moved to here.\r\n\r\n"
}

This is why the SOSResponse variable is undefined — it didn’t receive the expected response.

To resolve this, check each step of how the request is constructed and sent. Log every parameter you pass and ensure all data is accurate. If possible, check the incoming request from the API endpoint side (they might have logs available). If the request works with cURL but not with your API service, there may be differences in how the requests are constructed. Identifying those differences is crucial.

If the requests appear identical and the issue persists, I recommend contacting the Foreign API support team to ask why their route is returning a 302 status code.

Regards,
Stanislaw

@stanislaw.grin

Hmm. Interesting.

I’ll start again step by step.

Thanks!

Mike