cancel
Showing results for 
Search instead for 
Did you mean: 
Subscribe

Hello colleagues!


We are running a project on top NodeJS using CAP. We noticed a few weeks ago that the annotation @mandatory in the .cds file does not work for Function Modules.

I tested with the following annotations:

- @mandatory: https://cap.cloud.sap/docs/guides/generic#mandatory
- @FieldControl.Mandatory: https://cap.cloud.sap/docs/guides/generic#mandatory
- @Common.FieldControl.Mandatory:

None of them worked, so I'm not sure if they are supposed only to work with OData v2 or v4 API calls.

Here's a action in CDS as example:

action addGoal(
description : String(200) @mandatory,
targetCompletionDate : Timestamp @mandatory,
isPrivate : Boolean @mandatory );

In the example, we can add not null after the word Timestamp, and it becomes required. But for Strings as in description, adding not null wouldn't be enough to detect a blank string.

Do you know how to enable these annotations to work or if it's a known bug for CAP?


Thanks!

0 Likes
View Entire Topic
0 Likes

Hi Igor, have you tried?

annotate AdditionGoal with {
  description @Common.FieldControl: #Mandatory
}
0 Likes

In fact, i use something like

annotate DhcpAdminSvc.NetworkHosts with {
  device @( 
    Common: {
      Label:'{i18n>Device Name}',
      Text: device.name,
      TextArrangement : #TextOnly,
      FieldControl: #Mandatory
    },
    ValueList.entity: 'Devices'
  );
}

I hope it helps you.

0 Likes

Hi Rafa, thanks for the reply!

Something that we did in our side is the following, we created an Argument validator which checks if we have any property with mandatory and it's value. We call this under before("*") event for each Service that we expose. The only thing tha, in case you want to reproduce this in your side, it's that we are not validating trimmed strings (e.g.: " ").

class ArgumentValidator {


  /**
   * Validates arguments with @mandatory annotation for actions and functions on .cds files
   */
  static validateArguments(data, event, serviceName) {
    services[serviceName] = services[serviceName] || cds.connect.to(serviceName);
    const eventDefinitions = services[serviceName].model.definitions[event];


    // Skip validation for events with no definitions (e.g. "READ")
    if (!eventDefinitions) {
      return;
    }


    for (const parameterName in eventDefinitions.params) {
      validateArgument(data[parameterName], eventDefinitions.params[parameterName], parameterName);
    }
  }


}


function validateArgument(providedArgument, parameterDefinition, parameterName) {
  if (parameterDefinition["@mandatory"]) {
    const isValid = providedArgument !== null && providedArgument !== undefined && providedArgument !== "";
    ErrorHandler.validate(isValid, ServiceError.ARGUMENT_MISSING, parameterName);
  }
}


module.exports = ArgumentValidator;