Path, Query Parameter and Paging

Path Variable

A Path Variable is a dynamic value embedded directly within the URL path that is used to identify, locate, or operate on a specific resource in an application.

In SAP CAP, a path variable is a value passed in the URL path that uniquely identifies a specific resource (entity instance). In OData services, path variables are typically represented by the entity key inside parentheses.

Path Variable must have Primary Key field atleast.

CAP provides inbuild path variable feature which we can consume directly.

For Example -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses(550e8400-e29b-41d4-a716-446655440009)
Content-Type: application/json

OR

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses(ID=550e8400-e29b-41d4-a716-446655440008)
Content-Type: application/json

And we can customize the custom logic based on request.params.

What is next in cap ..?

next is a function available in CAP on event handlers that passes control to the next handler in the processing chain or to CAP's built-in Generic Provider.

So, since we know CAP automatically provides CRUD operations through its Generic Provider without any custom logic. When we implement any custom logic then we are affecting CAP normal flow.

At that point CAP does not know whether you want to completely replace the READ operation OR you only want to add validation and continue.

next() resolves this ambiguity.

So without next(), Your handler becomes responsible for everything.

Flow Diagram
Request
Custom Handler
 STOP

and with next(), your handler act as a validation check.

Flow Diagram
Request
Custom Handler
next()
CAP Generic Provider
Database
Response

and we can use next() in custom handler like-

srv/warehouse-service.js
srv.on('READ', 'Warehouses', async (request, next) => {
    try {
        // console.log(JSON.stringify(request.query, null, 2));

        return next();

    }
    catch (error) {
        return request.error({
            code: 500,
            message: 'Internal Server Error'
        });
    }
});

Remember, if you are using next and also performing some CRUD operation on DB through custom logic, then you are already reading the database once and then next() causes CAP to read it again.

So there will be two database calls, Hence we should appropriately use the next function.

When Should we Use next() ..?

Use it when we want to:

  • Validate input and still use standard CRUD.
  • Check authorization.
  • Log requests.
  • Enrich responses.
  • Add business rules before or after CAP processing.

When Should You Avoid next() ..?

Avoid it when:

  • We want complete control over the response.
  • We are replacing CAP's default CRUD behavior.
  • We are reading from an external API instead of the database.
  • We are building a completely custom query.

Query Parameter

A Query Parameter is a key-value pair appended to the URL after a ? symbol and is used to filter, search, sort, paginate, or modify the behavior of an API request without changing the resource path.

Path parameters identify a resource, while query parameters refine or filter the result.

Different Query Params provided by CAP are -

  • $select
  • $search
  • $filter
  • $orderby
  • $top
  • $skip
  • $count

1. $select

If we want to display only specific fields in the response, we can use the $select query option.

Example -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$select=ID,name
Content-Type: application/json

2. $search

If we want to search for a specific value in the response data, we can use the $search query option.

Example -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$search=Warehouse
Content-Type: application/json

3. $filter

The $filter query option is used to retrieve data that matches a specified condition.

Example, filter the result where name is equals Elite Storage -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$filter=name eq 'Elite Storage'
Content-Type: application/json

Example, filter the result where ID is greater than certain value -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$filter=ID gt 550e8400-e29b-41d4-a716-446655440004
Content-Type: application/json

Example, filter the result where ID is greater than certain value and name equals to certain value -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$filter=ID gt 550e8400-e29b-41d4-a716-446655440004 and name eq 'Elite Storage'
Content-Type: application/json

4. $orderby

The $orderby query option is used to sort the response data in ascending or descending order based on a specified field.

Example -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$orderby=name desc
Content-Type: application/json

5. $top

The $top query option is used to limit the number of records and return specific number of response data.

Example -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$top=5
Content-Type: application/json

6. $skip

Use the $skip query option to ignore the first N records in the response. It is typically combined with $top to implement paging.

Example -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$top=5&$skip=2
Content-Type: application/json

7. $count

The $count query parameter allows us to obtain the total count of records that match the query criteria.

Example -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$top=5&$skip=2&$count=true
Content-Type: application/json

Paging

Paging in SAP CAP is the process of retrieving data in smaller chunks instead of fetching the entire dataset at once.

CAP supports paging through the OData query options $top and $skip.

1. Client-Side Paging

Client-side paging can be implemented by using the $top and $skip OData query options to retrieve a specific subset of records from the complete dataset.

Example -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$top=5&$skip=2
Content-Type: application/json

2. Server-Side Paging (Default Page Size)

We can configure a default and maximum page size in our service definition in service.cds file.

We can use @cds.query.limit.default and @cds.query.limit.max annotation on the service file.

like -

srv/warehouse-service.cds
service WarehouseService @(path : 'warehouse') {
    
    @cds.query.limit.default: 5
    @cds.query.limit.max: 8
    entity Warehouses as projection on schema.Warehouse;

    function getWarehouseCount() returns Integer ;

    action updateWarehouseOwner(warehouseId : String, newOwner : String) returns String ;
}

and then request data will return default of 5 records using -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses
Content-Type: application/json

and will return max of 8 records if we try to fetch more than 8 records -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$top=12
Content-Type: application/json

3. Global Paging Configuration

You can define limits for all services of the application and can define define it in package.json.

like -

package.json
"cds": {
   "query": {
      "limit": {
         "default": 5,
         "max": 8
      }
   }
}

and then request data will return default of 5 records using -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses
Content-Type: application/json

and will return max of 8 records if we try to fetch more than 8 records -

test-api/Path and Query Param.http
GET http://localhost:4004/odata/v4/warehouse/Warehouses?$top=12
Content-Type: application/json

!!! Its Done !!!