As verificações são feitas no escopo do REST Framework, obedecendo as definições de modelo utilizadas quando Entity ou EntitySet são usados definidos na ação de um controlador. As definições das classe são feitas em arquivos do tipo x-class e x-model e são compartilhadas com o Web Framework, garantindo que ambas tecnologias possam utilizar as mesmas validações.
As verificações a nível de entidades são classificadas em dois tipos:
Estruturais:
As propriedades do JSON de entrada precisam obedecer o esquema das tabelas do banco de dados a partir das definições de modelo. Isso quer dizer que o REST Framework retornará um erro se for identificada uma propriedade no JSON que não está no modelo de dados.
A partir das entidades, o tipo de dado deve estar correto e as permissões do usuário devem ser validadas para alterar/inserir/consultar/excluir o registro/campo.
Os valores dos campos precisam atender as regras definidas nos campos.
Regras de négocio:
A entrada deve respeitar as regras especificadas no contexto de campos e de tabela durante a emissão dos listeners para os tipos de evento registrados na classe do dado.
A sequência de verificações estruturais são realizadas na ordem descrita abaixo:
Uso de Entity ou EntitySet na ação do controlador, o que garante que as validações de modelo serão executadas.
Conversão e tratamento de valores e tipos de acordo com as definições em x-model.
Validação de permissão de classe do dado com o uso de Entity ou EntitySet na ação do controlador,.
Validação de permissão do campo da classe com o uso de Entity ou EntitySet na ação do controlador,.
Para fazer o tratamento do item 2 (Conversão e tratamento de valores e tipos de acordo com as definições em x-model), são utilizadas algumas propriedades dos campos nas definições de modelo. Na tabela abaixo estão descritas as verificações estruturais que são validadas:
Eventos que podem disparar regras de negócio do modelo
Abaixo estão os eventos que são disparados a nível de registro durante o fluxo de uma requisição REST que utilize a API de entidades para acesso a dados.
Eventos disparados durante uma inserção no banco de dados, utilizando a API de acesso aos dados bdo.orm.EntitySet.insert() e bdo.orm.EntitySet.newEntity()
beforeInsert
afterInsert
Eventos disparados durante uma remoção no banco de dados, utilizando a API de acesso aos dados bdo.orm.EntitySet.remove() e bdo.orm.Entity.delete()
beforeDelete
afterDelete
Eventos disparado durante uma efetivação de edição da entidade, utilizando a API de acesso aos dados bdo.orm.EntitySet.merge() e bdo.orm.Entity.post()
beforePost
afterPost
Eventos disparados durante uma edição da entidade, utilizando a API de acesso aos dados bdo.orm.Entity.edit() que é utilizado em qualquer manipulação do bdo.orm.EntitySet, como update(), insert(), newEntity(), remove() e merge()
beforeEdit
afterEdit
Eventos disparados durante um cancelamento de edição, utilizando a API de acesso aos dados bdo.orm.Entity.cancel(), esse método foi criado por uma questão de compatibilidade com WebFramework e outras APIs do Bematech ERP, mas ele não tem função para o REST Framework.
beforeCancel
afterCancel
Ainda não é disparado pelo REST Framework, mais será disparado quando for necessário obter um valor semântico para um campo lookup, esse evento é obtido a partir da instanciação do modelo da classe em que a definição do registro referenciado está declarado.
lookupDisplay
Eventos que podem disparar regras de negócio dos campos do modelo
Abaixo estão os eventos que são disparados a nível de campo durante o fluxo de uma requisição REST que utilize a API de entidades para acesso a dados.
Eventos disparados durante qualquer manipulação de entidade, utilizando APIs como update(), insert(), newEntity(), remove() e merge() do bdo.orm.EntitySet ou set() do bdo.orm.Entity.
beforeLookupAddResult
lookupAddResult
afterLookupAddResult
beforeChange
afterChange
Disparado durante o insert() do bdo.orm.EntitySet
getOptions
Ainda não é disparado pelo REST Framework, mais será disparado quando for necessário obter um valor semântico de um campo lookup, esse evento é obtido a partir do campo que realiza a referencia para a classe que define a tabela do registro referenciado.
lookupDisplay
Compatibilização das classes de dados
As definições de classes de dados sofreram segregação de responsabilidades para permitir que o Framework REST pudesse consumir as regras de negócio definidas em eventos definidos nas classes e nos campos. Contudo, todas as definições precisam ser revistas para que seja possível manipular os dados. A API de entidades, que realiza acesso aos dados, não pode conter definições de visão durante sua execução pois a requisição retorna mídias estruturais que são compartilhadas com o cliente, que é quem detém o sistema que constrói a interface com o usuário.
Para que essa segregação fosse possível, foi necessário criar um modo que garante que as definições estejam separadas, então o modo estrito foi criado.
O modo estrito é habilitado por classe e também garante que a hierarquia de classes antecedentes precisa estar com este modo habilitado. O arquivo *.config dentro da classe é responsável por habilitar o modo estrito apenas com a flag this.strictMode = true;.
Utilizando definições de modelo personalizadas
Devida a eventual necessidade de utilizar recursos das classes que não foram compatibilizadas com o modo estrito, foi disponibilizada a opção de informar um modelo de dados customizado para uma classe de dados na API de entidades de dados, por meio da opção modelDef.
No exemplo abaixo é utilizada a classe de dados Engines sem os eventos configurados no modelo dados. Desativar os eventos permite utilizar as regras estruturais definidas em uma classe de dados em modo não estrito, sem os eventos que normalmente estão associados à API da grade de dados do Web Framework.
var modelDef = classDefManager.getModelDef(ngin.keys.Classes.ENGINES);
modelDef.offAll(); // retira todos os listeners de todos os eventos.
var ds = classes.getCachedDataSet(ngin.keys.Classes.ENGINES);
var entitySet = new bdo.orm.EntitySet(ngin.keys.Classes.ENGINES, ds, {
modelDef: modelDef
});
É importante observar que desligar os eventos possibilita que manipulações de modelo possam ser realizadas sem que as regras de negócio sejam executadas, portanto essa opção não é recomendada e deve ser utilizada apenas quando a controladora assume totalmente a responsabilidade de realizar todas as validações das regras de negócio. Essa funcionalidade deve ser vista como uma opção de transição enquanto não é concluída a revisão de todo o modelo de dados para o modo estrito e que no futuro poderá ser desativada.
Por segurança, o sistema impede por padrão o uso das classes JavaScript bdo.orm.EntitySet e do bdo.orm.Entity em classes de dados que não estejam em modo estrito. Para utilizar classes de dados que não estejam em modo estrito, o desenvolvedor deverá criar um arquivo JavaScript (extensão .ijs) no diretório /Configurações/Inicialização do Roteador HTTP, com o conteúdo abaixo.
__includeOnce('ufs:/bdo/config/config.js');
bdo.config.ormRequiresStrictMode = false;
Para maiores detalhes sobre a segregação de responsabilidades consulte o manual de classes.
Tratamento de Erros
Durante o atendimento de uma requisição HTTP há dois tipos de exceções no que se refere ao tratamento realizado pelo Framework:
exceções gerenciadas, ou seja, capturadas dentro do contexto de um controlador: como os erros são tratados dentro do controlador, é responsabilidade dele especificar o status HTTP de retorno, o código de erro e uma mensagem compreensiva a fim de ser exibida para o requisitante.
exceções lançadas na camada de negócio que não forem tratadas pelos controladores: serão automaticamente encapsuladas em um objeto de erro pelo Framework e por padrão são retornadas com o código de erro 500 (Internal Server Error). Esse comportamento pode ser alterado, conforme observado mais a frente. Para não expor informações potencialmente privilegiadas para os usuários da API, detalhes desse tipo de exceção, como a pilha de chamadas, serão gravadas apenas no log do Engine e identificados no log por um número único chamado de ticket. Esse ticket será enviado na resposta, permitindo que o requisitante da API possa consultar mais detalhes do erro caso tenha acesso ao log do Engine.
O requisitante identificará que ocorreu um erro durante a execução da API ao receber uma resposta com um código 4xx ou 5xx. O corpo dessa resposta conterá um JSON com mais detalhes do erro, tendo no mínimo as propriedades name e message. Classes de erros mais especializadas, como o DetailedError, poderão adicionar outras propriedades como details, errorCode e solution. Mensagens capturadas pelo Framework que não foram tratadas pelo controlador também terão a propriedade ticket, contendo o identificador a ser pesquisado no log do Engine para obter mais detalhes técnicos sobre o erro.
Por padrão, respostas HTTP de erro terão o código 500. Esse comportamento pode ser alterado explicitamente pelo controlador, ao criar uma resposta com outro código, ou implicitamente pelos meios abaixo:
Se a propriedade name do objeto que estiver no conteúdo do resultado for um nome de um estado HTTP acrescido do sufixo "Error", esse estado será o retornado. Por exemplo, um erro com nome "NotFoundError" irá produzir uma resposta com código de estado 404.
Exemplo do corpo de uma resposta com erro:
Códigos de estado HTTP
Os códigos de erro de uma API HTTP dividem-se em dois grupos: os erros 4xx, usados para indicar que foi uma falha na requisição do cliente, e os erros 5xx, que indicam uma falha no servidor. Quando um cliente recebe como retorno um erro 5xx, ele poderá tentar enviar novamente a requisição sem alterações, pois a causa do problema é um erro no servidor que, a princípio, não tem relação com a requisição enviada. Já um erro 4xx indica para o cliente que a requisição possui um erro que deve ser corrigido antes de uma nova tentativa.
Os códigos de estados que representam erros mais utilizados são:
400 - Bad Request
401 - Unauthorized
404 - Not Found
405 - Method Not Allowed - Usado para indicar que o método HTTP não é suportado para este recurso
500 - Internal Server Error - Erro do servidor não tratado pelo objeto controlador
Rastreamento de erros através de Logs
O objeto controlador deverá utilizar a API Logger, fazendo uso das prioridades de forma adequada, conforme tabela abaixo:
Conclusão
Por fim, com os conceitos mostrados neste manual constata-se que o Bematech ERP é capaz de implementar Recursos REST provendo acesso de outros sistemas que utilizem o consumo de APIs HTTP ou similares, bem como de frameworks client-side que obedecem as especificações do conceito REST.
Foram visitados conceitos de Recursos, Rotas, APIs de acesso ao modelo de dados, Transformações, Validações do Bematech ERP e Tratamentos de erros .
Sugerimos fortemente que sempre que houver dúvidas a cerca dos comportamentos da API REST no Bematech ERP, que consulte este Manual, para que depois utilize ou consulte manuais de domínio publico a respeito do conceito da API REST.
Mesmo assim, se mesmo após a leitura deste manual, houverem dúvidas de desenvolvimento, esperamos que o desenvolvedor que fizer uso da API REST nos contacte a fim de aprimorar o conteúdo deste Manual.
< APIs de acesso e transformações de dados Página anterior