cancel
Showing results for 
Search instead for 
Did you mean: 

CAP NodeJS: @mandatory does not work for Function Imports / Actions

11-25-2020 6:39 PM
3024 views 5 comments Go to solution
0 Likes
SAP Managed Tags
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

Accepted Solutions (1)

Accepted Solutions (1)

vitaly_kozyura
Advisor
Advisor

Hi,

With the next CAP release the @mandatory check will be also applied for actions and functions having typed parameters. Also the String parameters annotated with @mandatory will be checked for being empty strings. You can follow CAP releases at https://cap.cloud.sap/docs/releases/.

Best regards,

Vitaly

Answers (2)

Answers (2)

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;
0 Likes

[Update]

I also tried using Annotations with the type, but this also didn't work for my case.

Example below

define type AdditionGoal {
  description          : String(200);
  targetCompletionDate : Timestamp;
  isPrivate            : Boolean;
}// Input validation
annotate AdditionGoal with {
  description             @mandatory;
  targetCompletionDate    @mandatory;
  isPrivate               @mandatory;
}
action addGoal(
    goal : AdditionGoal
  );

I passed to the backend an entity goal with the description property empty and CAP allowed it.