cancel
Showing results for 
Search instead for 
Did you mean: 

Disabling the default CRUD handlers

helpmesap
Explorer

Is it at all possible to disable the default CRUD handlers for defined entities? While I can define custom functionality by implementing the corresponding .on('CREATE', ...), .on('READ', ...) handlers it appears that these handlers get executed in addition to the implicit default and not instead of it.

I would like to implement an endpoint /data/Json via which to receive arbitrary json payloads. To this end, I have attempted to declare a non-persistent entity in my service model via @cds.persistence.skip whose CREATE handler I then designed according to my needs.

// srv/service.cds
service Data @(path: '/data') {
    @cds.persistence.skip
    entity Json {
        key ID: UUID;
        json: String;
    }
}

// srv/service.js
module.exports = async (srv) => {
    srv.on('CREATE', 'Json', (req) => {
        /*
         * Use the data from req.data.json here
         */
    })
}

Unfortunately, any attempt to POST data to the endpoint fails due to SQLITE_ERROR: no such table: Data_Json from which I deduce that the POST results in an attempt to actually write the data to the database, which is the default behavior. Is there an option to disable the default handler altogether for my entity?

Thank you and kinds regards.

Accepted Solutions (1)

Accepted Solutions (1)

vansyckel
Advisor
Advisor

Hi helpmesap,

All relevant on handlers for the respective request are executed sequentially, with the default ones last. This allows you to defer to them, for example in case you didn't want to handle the request after all. However, that means that you need to terminate the execution, for example by invoking req.reply(), req.reject(), etc. The full list can be found here: https://cap.cloud.sap/docs/node.js/api#service-on (cf. section "Outcomes").

Best,
Sebastian

helpmesap
Explorer
0 Kudos

Thank you very much - I must have skipped over the relevant doc section at least twice. Unfortunately, I am now faced with another error: The key 'ID' does not exist in the given entity which is raised after all the .before, .on. and .after handlers have been executed.

Using the following service definitions

// srv/service.js
module.exports = async (srv) => {
   srv.before('CREATE', 'Json', async (req) => {
       console.log('before CREATE')
   })
   srv.on('CREATE', 'Json', async (req) => {
       console.log('on CREATE')
       req.reply('OK')
   }) 
   srv.after('CREATE', 'Json', async (req) => {
       console.log('after CREATE')
   })
}

the output to my terminal after the POST

POST http://localhost:4004/data/Json HTTP/1.1
content-type: application/json

{
    "data": "..."
}

is

POST /data/Json
before CREATE
on CREATE
after CREATE
[2020-05-14T09:30:38.918Z | ERROR | 1811667]: The key 'ID' does not exist in the given entity

It doesn't help if I POST an additional "ID" field - same error. Apparently there's still something going on after all handlers are done executing. Any idea what's wrong here?

I have attempted to declare the entity @nokey which seems to be ignored altogether so that the model won't even compile:

// srv/service.cds
service Data @(path: '/data') {
  @cds.persistence.skip
  @nokey
  entity Json {
      data: String;
  }
}

[ERROR] srv/service.cds:2.3-7.4: Entity "Data.Json" does not have a key: ODATA entities must have a key

gregorw
Active Contributor
0 Kudos

If you would simply send:

POST http://localhost:4004/data/Json HTTP/1.1
content-type:application/json

{"ID": "72b55731-e297-4996-b51a-0d0ca3b0e97c", "data": "..."}

?

helpmesap
Explorer
0 Kudos

Same output and error:

POST /data/Json
before CREATE
on CREATE
after CREATE
[2020-05-14T11:32:29.460Z | ERROR | 1346598]: The key 'ID' does not exist in the given entity
vansyckel
Advisor
Advisor

Hi helpmesap,

  1. OData requires that each entity has a key property (@nokey is not applicable if you want to expose the entity via OData.). So you could either add (a dummy) one, or simply make "data" the key, i.e., "key data: String;"
  2. "req.reply('OK')" will not do, as the OData protocol specifies that the created entity is returned. Hence, it must be req.reply({ data: <some string> })"

Best,
Sebastian

Answers (0)