cancel
Showing results for 
Search instead for 
Did you mean: 

CAP how to throw meaningful error in Action handler?

epamtiosteel
Explorer
0 Kudos

Hi colleagues and david.kunz2 especially.

Could you please give an advice of how to throw meaningful errors in CAP actions (Bound one in my case)?

The issue is that an action handler doesn't have a regular req parameter.

The best option I found by now is

async cancelFullPO(entity, key) { 
cds.context.http.res.sendStatus(400);
cds.context.http.res.send('My Error');
}

due to the input parameters of an action

but what I want is to to operate req.error as I usually do in an ordinary handler so that I can

1) specify a target like it's described here
https://cap.cloud.sap/docs/node.js/events#using-an-object-as-argument

2) throw multiple errors at once

Thank you. Best regards.

View Entire Topic
david_kunz2
Advisor
Advisor

Hi acntiosteel ,

> that an action handler doesn't have a regular req parameter.

It does, and you can use `req.reject` or `req.error`. Simple example:

service CatalogService {
    entity Books as projection on my.Books actions {
      action Foo() returns String;
    };
}
    srv.on('Foo', 'Books', async req => {
      req.error(400,'nope 1')
      req.error(400,'nope 2')
      return 'success'
    })

Best regards,

David

Cguttikonda
Explorer
0 Kudos

Hello david.kunz2,

Does this request object injected incase of unbound actions as well.??

david_kunz2
Advisor
Advisor
0 Kudos

Yes, also for unbound actions and functions.

epamtiosteel
Explorer
0 Kudos

Hi david.kunz2,
for me currently the req is definitely the entity definition as you can see below - I printed it in console (also req.error obviously doesn't exist)

The difference between your example and my one is that my service is defined by class and your example refers to the classic way of definition

module.exports = class createRequests extends cds.ApplicationService {
  init() {
    ...

    return super.init();
  }<br>

here's some tech info

... $ cds -v
@sap/cds: 7.1.1
@sap/cds-compiler: 4.1.2
@sap/cds-dk: 7.0.2
@sap/cds-dk (global): 7.1.0
@sap/cds-fiori: 1.0.0
@sap/cds-foss: 4.0.2
@sap/cds-mtxs: 1.10.0
@sap/cds-odata-v2-adapter-proxy: 1.9.21
@sap/eslint-plugin-cds: 2.6.3
Node.js: v18.14.2
david_kunz2
Advisor
Advisor

In the method-style implementation, you just get the parameters as input variables. You can create an on handler instead, like in my code example.

https://cap.cloud.sap/docs/guides/providing-services#actions-vs-functions

epamtiosteel
Explorer
0 Kudos

Thank you, I reproduced successful case. So

this.on('cancelFullPO', this.cancelFullPO); // this will be ignored by CAP, first parameter inside cancelFullPO will be an entity definition, not req

this.on('cancelFullPO', async () => this.cancelFullPO(...arguments)); // in this case the first parameter inside cancelFullPO will be an entity definition, not req

but what will work is either anonymous function or just a method with different name

this.on('cancelFullPO', this.onCancelFullPO); // this will receive expected parameters - req

this.on('cancelFullPO', async(req) => {
req.error('nope');
}); // this will work as well
david_kunz2
Advisor
Advisor

In JavaScript, there's no `arguments` in an arrow function.

Welcome to Node.js v20.5.1.
Type ".help" for more information.
> const foo = () => console.log(...arguments)
undefined
> foo(1,2,3)
Uncaught ReferenceError: arguments is not defined
    at foo (REPL7:1:34)
> function bar() { console.log(...arguments) }
undefined
> bar(1,2,3)
1 2 3
undefined