Adicionar lógica personalizada

Objective

After completing this lesson, you will be able to implementar validações programáticas com a ajuda de manipuladores de eventos .before

Implementações de serviço personalizado

Como a maioria das tarefas padrão e casos de utilização são cobertos por provedores de serviços genéricos, a necessidade de adicionar código de implementação de serviço é bastante reduzida e minimizada.

Os casos restantes se reduzem a uma lógica personalizada real, específica ao seu domínio e aplicativo, como validações programáticas específicas de domínio.

Como exemplo, vamos programar uma validação que garanta que a data de nascimento passada é anterior à data de morte passada ao criar um novo autor através do AdminService.

A maneira mais fácil de adicionar implementações de serviço personalizado é simplesmente colocar um arquivo .js igualmente chamado ao lado do arquivo .cds contendo a respectiva definição de serviço. Ou seja, no nosso caso, colocamos um arquivo chamado admin-service.js na pasta srv do nosso projeto, pois essa pasta também contém o arquivo admin-service.cds, que é usado para definir o AdminService (veja a figura a seguir).

Nota

Como alternativa, você também pode anotar a definição de serviço no arquivo .cds com a anotação @impl . Você usa esta anotação para se referir explicitamente a outro arquivo .js que deve conter a implementação de serviço.

Existem diferentes formas de implementar a lógica personalizada necessária no arquivo .js. A maneira mais comum é usar uma subclasse de cds.ApplicationService para se beneficiar de implementações genéricas prontas para uso. Isso ocorre porque a classe cds.ApplicationService é a implementação padrão do provedor de serviços, que adiciona os provedores genéricos já discutidos a uma definição de serviço.

Para criar uma subclasse de cds.ApplicationService, primeiro atribuímos o módulo @sap/cds à constante cds em nosso código (linha 1). O módulo @sap/cds é o objeto de fachada cds que fornece acesso a todas as APIs CAP Node.js.

Em seguida, criamos uma subclasse de cds.ApplicationService nas linhas 4 a 6, na qual mais tarde implementaremos nossa lógica personalizada. O nome da subclasse é arbitrário. Chamamos isso aqui como nossa interface de serviço, ou seja, AdminService.

Na linha 9, disponibilizamos a classe AdminService para importação em outros módulos. Esta é uma prática comum no Node.js para estruturar o código.

Nota

Se você iniciar agora a aplicação inserindo cds watch no terminal, o arquivo de implementação de serviço adicionado é exibido no log por meio de uma saída semelhante à seguinte:

Code Snippet
1
[cds] - serving AdminService { path: '/admin', impl: 'srv/admin-service.js' }

Manipuladores de eventos

As implementações de serviço personalizado são executadas com a ajuda de manipuladores de eventos personalizados, em que é efetuada uma distinção entre diferentes tipos de manipuladores.

Assista ao vídeo para obter uma síntese dos diferentes manipuladores de eventos.

Registrando .before manipuladores de eventos

Para a validação que queremos implementar, precisamos de um manipulador Before que deve ser registrado para operações CREATE e UPDATE na entidade Authors.

Para registrar manipuladores de eventos personalizados, sobregrave o método init() herdado na classe de implementação criada (consulte a figura a seguir). Não se esqueça de chamar super.init() na implementação para permitir que as subclasses registrem seus manipuladores.

Para registrar um manipulador before no método init() , chame o método before() herdado via this.before(). Para isso, você deve fornecer a seguinte interface. Uma descrição detalhada dos parâmetros individuais pode ser encontrada na documentação CAP:

Code Snippet
12345
function before ( event : string | string[] | '*', entity? : CSN definition | CSN definition[] | string | string[] | '*', handler : function )

No exemplo mostrado, a função nomeada this.validateLifeData é registrada para operações CREATE e UPDATE na entidade Authors. Discutiremos a implementação dessa função posteriormente.

A entidade ou entidades para as quais o registro deve ocorrer pode ser transferida para o método before() como cadeia. No entanto, é recomendável passar as definições de CSN aqui. As definições CSN das entidades que são expostas através do serviço são convenientemente disponibilizadas através da propriedade this.entities .

No exemplo mostrado, a definição CSN necessária para a entidade Authors é atribuída à constante Authors por meio de uma atribuição de desestruturação.

Nota

A sintaxe de atribuição de desestruturação é o padrão JavaScript. É uma expressão JavaScript que torna possível descompactar valores de matrizes, ou propriedades de objetos, em variáveis distintas.

Validando dados de entrada

Por fim, vejamos como a função validateLifeData que foi registrada como um manipulador Before pode ser implementada na classe AdminService.

Antes de manipuladores geralmente recebem um único argumento, uma instância de cds.Request. Esta instância fornece características e métodos que podem ser utilizados para implementar o manipulador. No exemplo, nomeamos o argumento req (veja a figura a seguir).

Para solicitações CREATE e UPDATE, com as quais nos preocupamos aqui, a propriedade de dados do parâmetro de interface contém o corpo HTTP da solicitação. Utilizamos uma atribuição de desestruturação para atribuir os valores transferidos do corpo HTTP às constantes dateOfBirth e dateOfDeath.

Se a data do óbito for anterior à data de nascimento, emitimos uma mensagem de erro correspondente por meio do método req.error() .

Nota

O método req.error() coleta todas as falhas na propriedade req.errors, permitindo exibi-las em IUs de uma só vez. Se existirem req.errors após a fase anterior, o processamento da solicitação é cancelado com uma resposta de erro correspondente retornada ao mandante.

Dica

O literal transferido para o método req.error() é delimitado com caracteres backtick (`). Esses literais de modelo permitem que valores de variável sejam incorporados em uma string usando a sintaxe ${name_of_the_variable}.

Demonstração e exercício: fornecer um . antes do manipulador de eventos

Nota

Como exercício, execute as instruções passo a passo na demonstração a seguir no SAP Business Application Studio.

Como ponto de partida para o exercício, utilize o resultado do exercício anterior Definir um serviço com base em visões desnormalizadas se você o tiver concluído com êxito. Como alternativa, você também pode utilizar a ramificação 10_denormalized_views do seguinte repositório GitHub como ponto de partida:

https://github.com/SAP-samples/cap-development-learning-journey

A implementação completa da simulação pode ser encontrada no ramo 11_.before_event_handler do repositório GitHub.

Informações detalhadas sobre o conteúdo do repositório e como usá-lo podem ser encontradas aqui.

Assista ao vídeo para ver como fornecer um manipulador de eventos .before.