WebService REST no PROTHEUS
Produto: | ADVPL | ||||||||||||||||||||||||
Versões: |
| ||||||||||||||||||||||||
Ocorrência: | Gostaria de um material que explicasse realmente como implementar a tecnologia RESTFul no Protheus, com exemplos de APIs, exemplos de programas externos consumindo o serviço, e exemplos de envio e recebimento de dados. | ||||||||||||||||||||||||
Ambiente: | Todos | ||||||||||||||||||||||||
Passo a passo: | – O que é REST? A web é amplamente utilizada e reconhecida principalmente por sua arquitetura robusta, escalável e tolerante a falhas. Quem sustenta esses fatores e lhe dá todo este poder é o protocolo HTTP (o protocolo HTTP é utilizado, em regra, quando se deseja evitar que a informação transmitida entre o cliente e o servidor seja visualizada por terceiros, como, por exemplo, no caso de compras online.). Atualmente, muitas vezes necessitamos integrar aplicações em ambientes totalmente diferentes e os WebServices são uma das maneiras mais comuns e fáceis de integrar os diferentes sistemas. Este post mostrará um pouco de um modelo de WebService chamado REST. Representational State Transfer ou somente REST, é cada vez mais usado como alternativa ao “já antigo” SOAP onde que a principal crítica a esta é a burocracia, algo que REST possui em uma escala muito menor. O principal nesta arquitetura são as URLs do sistema e os resources (resource é um recurso, entidade). Ele aproveita os métodos HTTP para se comunicar, que são: GET: Solicita a representação de um determinado recurso. É definido como um método seguro e não deve ser usado para disparar uma ação (remover um usuário, por exemplo); POST: As informações enviadas no corpo (body) da requisição são utilizadas para criar um novo recurso. Também é responsável por fazer processamentos que não são diretamente relacionados a um recurso. DELETE: Remove um recurso. PUT: Atualiza um recurso na URI especificada. Caso o recurso não exista, ele pode criar um. A principal diferença entre POST e PUT é que o primeiro pode lidar não somente com recursos, mas também pode fazer processamento de informações.
Agora que já entendemos um pouco sobre o que é um webservice rest, “vamos por a mão na massa” e desenvolver uma aplicação “Hello Word REST”. O primeiro passo para criarmos um serviço REST é configurar o Protheus como um servidor HTTP REST. Para isso vamos manipular o arquivo .ini do AppServer, conforme exemplo abaixo: A função HTTP_START que prepara o AppServer como servidor HTTP para REST, necessitando ser configurada na seção ONSTART: [GENERAL] MAXSTRINGSIZE=10 [ONSTART] JOBS=HTTPJOB REFRESHRATE=120
[HTTPJOB] MAIN=HTTP_START ENVIRONMENT=P12LOCAL
[HTTPV11] Sockets=HTTPREST
[HTTPV11] Sockets=HTTPREST,HTTPREST2
[HTTPREST] IPsBind= URIs=HTTPURI Security=0
[HTTPREST] IPsBind= URIs=HTTPURI,HTTPURI2 Security=1
[HTTPURI] PrepareIn=99,01 Instances=1,1
Após a configuração, o appserver.ini deverá ficar da seguinte maneira: Após a adição das seções no .ini, deve reiniciar o appserver e podemos ver no log que está no ar nosso servidor http/rest: Com nosso servidor web no ar, vamos acessar via navegador a URI que configuramos no .ini, para ter 100% de certeza que estamos prontos para “por a mão na massa”. Para acessar nossa URI, devemos acessar o caminho definido via navegador. Nesse caso, (exemplo acima) a URL que vamos acessar para testar nossa URI é a seguinte: Deverá ser exibida a seguinte tela: Onde nada mais é que uma página WEB contendo todas as API’s rest que está disponível no ERP Protheus. “Pondo a mão na massa”A nossa primeira API rest do advpl, vamos fazer um programa para retornar a descrição, unidade de medida e o status de um determinado produto. Passo 01: IncludesPara criar um webservice REST no Protheus, precisamos da utilização de um include específico, esse include possui alguns DEFINES que facilita muito o desenvolvimento da nossa funcionalidade. Esse include é o RestFul.CH. #Include 'Protheus.ch' User Function EREST_01() Acima definimos uma User Function, porém ela serve apenas com “Dummy Function” (Função fantasma) ou seja, ela serve apenas para reservarmos o nome do nosso “.prw” dentro do repositório, é claro que nada te impede de utilizar essa “Dummy function” como uma função de processamento chamada no nosso programa ADVPL. Passo 02: Definição da estrutura do WebServicePara criarmos um webservice, precisamos definir a estrutura do mesmo, ou seja, os atributos e métodos que iremos disponibilizar. Nesse nosso primeiro exemplo, como citado acima, vamos falar apenas do método GET (método responsável por retornar informações, se estivéssemos tratando de um CRUD esse “cara” seria o Ready). WSRESTFUL PRODUTOS DESCRIPTION "Serviço REST para manipulação de Produtos" WSDATA CODPRODUTO As String WSMETHOD GET DESCRIPTION "Retorna o produto informado na URL" WSSYNTAX "/PRODUTOS || /PRODUTOS/{}" END WSRESTFUL
Linha 1: WSRESTFUL -> Início da declaração da estrutura do Webservice; Logo após definirmos a criação do webservice, deveremos definir quais atributos o mesmo terá. Linha 3: WSDATA -> Definição dos atributos No nosso caso, teremos um único atributo que é o CODPRODUTO e esse atributo é do tipo string, porém ele poderia ser:
Linha 5: WSMETHOD -> Definição de um método
DESCRIPTION -> Descrição do método. Linha 6: END WSRESTFUL -> Encerra a declaração da estrutura do webservice. Passo 03: Definição do método.A definição do método é o passo onde vamos desenvolver toda a regra de negócio do método. Como nosso método é um GET, deveremos devolver um JSON para a aplicação CLIENT. Para a criação do JSON que vamos devolver para o Client, iremos utilizar a função FWJsonSerialize, veremos mais a frente sua utilização. WSMETHOD GET WSRECEIVE CODPRODUTO WSSERVICE PRODUTOS ::SetContentType("application/json") DbSelectArea("SB1") cJson := FWJsonSerialize(oObjProd) ::SetResponse(cJson) RestArea(aArea) Entendendo o trecho de código acima: Linha 1: WsMethod -> Indica a iniciação de escrita do método Abaixo temos a declaração das variáveis que iremos utilizar, onde no nosso caso, temos 2 que requer nossa atenção, que são as seguintes: cCodProd -> Armazena o código do produto informado na URL. Linha 9: Definição do tipo de retorno: ::SetContentType(“application/json”) Após a definição do tipo de retorno, possuímos um pequeno trecho de código que nos serve para posicionar no produto que recebemos pela URL e iremos serializar o mesmo. Para serializar o nosso registro JSON, devemos criar uma classe com os atributos que iremos retornar e alimentar os atributos com os valores desejados. Linha 18: Após alimentarmos o objeto criado com os atributos que queremos retornar, então devemos utilizar a função FWJsonSerialize que retorna a string do objeto passado como parâmetro. cJson := FWJsonSerialize(oObjProd) Linha 20: Seta a resposta para a aplicação Client ::SetResponse(cJson)
Agora vamos ver a nossa aplicação na prática: Feito toda a codificação do nosso exemplo e compilado no RPO, vamos verificar se o nosso WS Rest está disponível para utilização através do nossa URI: Agora iremos realizar o “consumo” da API Rest criada através da ferramenta Postman ou no nosso caso como se trata de uma API aberta e sem nenhum tipo de autenticação, também pode ser chamado direto pela URL no navegador: Teste pelo Postman: Teste pelo Navegador: | ||||||||||||||||||||||||
Observações: | O Postman foi utilizado como exemplo de consumo em uma ferramenta externa, a TOTVS não presta suporte a ferramentas de terceiros, somente analisa o serviço e/ou consumo utilizando os recursos documentados e disponíveis para customização. Documentações de referência: http://tdn.totvs.com/display/tec/REST |