Você está na página 1de 31

10/08/2020 REST | Desmistificando o MVC no AdvPL

https://mvcadvpl.wordpress.com/category/rest/ 1/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

https://mvcadvpl.wordpress.com/category/rest/ 2/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

Desmistificando o MVC no AdvPL

Procurando conteúdo sobre MVC na linguagem AdvPL?


Achou.

Categoria
REST

Utilizando a API RestFul dos modelos de dados do


ERP Protheus

2 02+00:00 JULHO 02+00:00 20173 03+00:00 JULHO 03+00:00 2017 ⁄ VICTOR ANDRADE ⁄ DEIXE UM
COMENTÁRIO
Após algum tempo sem realizar postagens devido as correrias do dia-a-dia, voltamos a falar sobre o
tema webservice REST no ERP Protheus.

Sugerimos que vocês (nosso público) fizessem-nos solicitações de postagens que achem interessantes.
Seguindo a maioria das solicitações, nessa postagem iremos realizar uma abordagem muito
interessante… A utilização do webservice REST com o modelo de dados (vulgo MVC) do ERP
Protheus.

https://mvcadvpl.wordpress.com/category/rest/ 3/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
Para que consiga acompanhar o exemplo da postagem, sugiro que confira a postagem que a Ju
escreveu no link que será disponibilizado logo abaixo. Pois será com base nessa publicação que
daremos continuidade.

Link: h ps://mvcadvpl.wordpress.com/2017/04/10/hello-word/
(h ps://mvcadvpl.wordpress.com/2017/04/10/hello-word/)

Pessoas, sugiro que prestem bastante atenção nos detalhes da escrita do POST, pois é uma
funcionalidade extremamente útil para nós desenvolvedores e que demanda de apenas uma única
linha de código …

É isso mesmo, você não leu errado, teremos apenas uma linha de código para ativarmos a
funcionalidade.
Então … bora lá!

Premissas:

Possuir um ambiente parametrizado para a utilização de webservice REST (conforme demonstrado


na postagem xxx);
Possuir conhecimento básico em MVC;
Conforme citado acima, irei utilizar um programa em MVC que a Ju desenvolve, logo, para
conseguir acompanhar essa postagem, também é uma premissa que tenha esse projeto compilado
em seu ambiente.

Após as premissas acimas estiverem “ok”, vamos criar o nosso programa que publicará “on-air” a
nossa API baseada em um modelo de dados, abaixo segue o código:

#Include ‘Protheus.ch’

#Include ‘Parmtype.ch’

#Include “FWMVCDEF.CH”

PUBLISH USER MODEL REST NAME Aluno SOURCE CMVC_01

Eu menti, quando disse acima que teríamos 1 única linha de código, havia me esquecido dos “headers
files” ou mais conhecidos como “.ch”.

Tirando a parte dos includes, onde creio que a maioria já conheça ao menos um pouco de sua
funcionalidade, vamos entender o trecho abaixo.

PUBLISH USER MODEL REST NAME <nome> source <fonte> RESOURCE OBJECT <objeto>

Esse é o trecho que irá disponibilizar a nossa API “on-air”.

Entendendo a diretiva de compilação:

Logo após o comando PUBLISH USER MODEL REST NAME temos a “tag” <nome>, essa tag deverá
ser preenchida com o nome da sua API, por exemplo:

O nosso modelo de dados é responsável por realizar um CRUD de Alunos, logo o nome da minha API
será “Aluno”.

https://mvcadvpl.wordpress.com/category/rest/ 4/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

Antes de entendermos os próximos trechos da diretiva de compilação, é importante saber que temos 2
formas diferentes de configurar a nossa API.

A primeira é possuir o modelo de dados em um único fonte (prw) e a publicação em outro;


A segunda é possuir tanto o modelo de dados, quanto a publicação no mesmo fonte (prw).

A primeira forma é a que iremos utilizar neste exemplo, onde, o nosso modelo de dados está em um
programa diferente do programa de publicação da API, para que a API seja publicada dessa maneira,
as diretivas de compilação devem ser aplicadas da seguinte forma:

PUBLISH USER MODEL REST NAME <nome> source <fonte>

Conforme visto acima, iremos substituir a tag <nome>, pelo nome da nossa API e adicionamos o
seguinte o trecho:

source <fonte>

A tag <fonte>, deverá ser substituída pelo nome do programa onde está o modelo de dados, no nosso
caso é o CMVC_01.

A segunda forma é quando possuímos o modelo e a publicação no mesmo fonte. Nesse caso a diretiva
de compilação deve ser aplicada da seguinte maneira

PUBLISH USER MODEL REST NAME <nome> RESOURCE OBJECT <objeto>

Conforme visto acima, iremos substituir a tag <nome>, pelo nome da nossa API e adicionamos o
seguinte temos o trecho:

RESOURCE OBJECT <objeto>

A tag <objeto> deverá ser substituída pelo objeto da model.

Na TDN temos um exemplo bem demonstrado desse caso, por isso não irei entrar em detalhes (TDN
Api RestFul (h p://tdn.totvs.com/display/public/PROT/FWRestModel+-
+API+RESTful+dos+modelos+de+dados+do+Protheus)).

Após compilado no RPO, vamos testar a utilização da nossa funcionalidade.

Para API’s do modelo de dados do ERP, o link de acesso fica da seguinte maneira:

<servidor:porta>/<URI>/FwModel/<nome_da_API>/<PK>

Entendendo a URL acima:

<servidor:porta> : Servidor + porta no qual está configurador o servidor HTTP do webservice


REST.
<URI> : URI configurada no ini do AppServer do webservice REST dentro da seção HTTPURI:
FwModel: Default
<nome_da_API>: Nome da API definido na tag <nome> na diretiva de compilação de publicação
do REST.
<PK>: Primary Key, para realização de filtros em operações do tipo GET, PUT, DELETE.

ATENÇÃO!!!
https://mvcadvpl.wordpress.com/category/rest/ 5/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
ATENÇÃO!!!

A chave PK deverá ser informada no formato ENCODE64.


A chave PK deverá ser a chave da tabela principal do modelo

Agora vamos testar a nossa aplicação:

No meu caso, o link para consumo da API ficou o seguinte:

h p://localhost:8012/rest/fwmodel/ALUNO (h p://localhost:8012/rest/fwmodel/ALUNO)

E caso você tenha acompanhado as outras postagens, creio que o seu esteja parecido.

Através da ferramenta POSTMAN, se fizermos um GET nessa URL, teremos o retorno de todos os
“Alunos” cadastrados na nossa base de dados:

Conforme a imagem acima, temos diversos registros na base de dados. Podemos conferir através da
tag total.

Segue abaixo um exemplo de uma requisição GET de um registro específico, ou seja, informando a
PK:

https://mvcadvpl.wordpress.com/category/rest/ 6/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

Podemos ver que só foi retornado o registro de parâmetro informado na URL.

Aparentemente é um código bem estranho de diferenciar, mas utilizando alguns sites da internet ou
até mesmo funções do framework ADVPL, conseguimos gerar a chave para execução de testes.

Para realizarmos a inclusão de um novo registro utilizando a nossa API que está referenciando um
modelo de dados existente no ERP, basta:

Utilizar a mesma estrutura do JSON retornado na requisição GET;


Apagar a PK da URL;
Alterar os dados da requisição para os dados desejados
Excluir a tag pk do body
Modificar a tag operation para o conteúdo 3
https://mvcadvpl.wordpress.com/category/rest/ 7/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
Modificar a tag operation para o conteúdo 3.

Abaixo o exemplo de uma requisição do tipo POST, porém com dados de uma PK existente:

Repare que é retornado um erro de validação, pois já existe algum registro com aquela informação.

O ponto que nos chama atenção nesse caso é que não escrevemos nenhuma linha de código para
validação, o retorno está vindo direto da rotina que referenciamos quando montamos o nosso
programa de publicação da API.

Abaixo irei alterar o body de requisição, para realizarmos a inclusão do registro no ERP Protheus:

https://mvcadvpl.wordpress.com/category/rest/ 8/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

Repare que a execução do método foi concluída com sucesso. Para conferir, vamos acessar
diretamente na tela do ERP:

Abaixo um exemplo da execução do método PUT, onde para sua execução:


Foi informado a PK para posicionamento no registro através da URL;
Alterado a tag operation para o conteúdo 4;
Alterado o conteúdo no body de requisição para o novo conteúdo que desejamos que seja gravado
no ERP:

No exemplo acima, foi alterado o registro incluído anteriormente. Ao executar a requisição acima no
POSTMAN, deverá ser atualizado o registro no ERP:

Por fim… A execução do método DELETE para realizar a exclusão de registros:

Para execução do método DELETE, basta enviar uma requisição do tipo DELETE e informar na URL a
PK para posicionamento do registro:

https://mvcadvpl.wordpress.com/category/rest/ 9/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

Se conferirmos no ERP, o registro deverá estar com o status de excluído:

Pessoal… Atenção para alguns detalhes:


Por ser uma funcionalidade relativamente nova, a API RestFul do ERP Protheus ainda não possui uma
documentação bem exemplificada, logo, todas as conclusões e testes apresentados acima foram
desenvolvidos por conta própria na base da “tentativa e erro”. Podendo existir maneiras mais simples
para execução dos procedimentos descritos acima.

Espero que a postagem seja útil para vocês!

Victor Andrade.

Entendo os métodos PUT, POST e UPDATE

1 01+00:00 MAIO 01+00:00 20172 02+00:00 MAIO 02+00:00 2017 ⁄ VICTOR ANDRADE ⁄ 8
COMENTÁRIOS
Apenas corrigindo o título do blog, os métodos são:

GET, PUT e POST

Como vimos na primeira postagem sobre WS REST, em um serviço podemos ter 4 métodos dos quais
são POST, UPDATE, DELETE e GET, cada um desses métodos retorna um código HTTP sendo de
sucesso ou erro.

Abaixo iremos entender o funcionamento dos métodos PUT, POST e UPDATE e faremos um
programinha para ver como isso funciona no ADVPL.

Na explicação do método, irei focar na explicação apenas do que se diz respeito ao REST, o restante é
o nosso conhecido ADVPL. Porém caso tenha algum tipo de dúvida, PERGUNTE

GET:

O método GET é responsável por retornar ao cliente chamador alguma coisa qualquer, como por
exemplo uma lista de clientes cadastrados.

Vamos ver abaixo um exemplo de método get:

https://mvcadvpl.wordpress.com/category/rest/ 10/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

WSMETHOD GET WSSERVICE CLIENTES

Local aArea := GetArea()

Local cNextAlias := GetNextAlias()

Local oCliente := CLIENTES():New() // –> Objeto da classe cliente

Local oResponse := FULL_CLIENTES():New() // –> Objeto que será serializado

Local cJSON := “”

Local lRet := .T.

BeginSQL Alias cNextAlias

SELECT A1_COD, A1_LOJA, A1_NOME, A1_END, A1_CGC, A1_CEP, A1_DDD, A1_TEL

FROM %table:SA1% SA1

WHERE SA1.%notdel%

EndSQL

(cNextAlias)->( DbGoTop() )

If (cNextAlias)->( !Eof() )

While (cNextAlias)->( !Eof() )

oCliente:SetCodigo( AllTrim((cNextAlias)->A1_COD ))

oCliente:SetLoja( AllTrim((cNextAlias)->A1_LOJA))

oCliente:SetNome( AllTrim((cNextAlias)->A1_NOME))

oCliente:SetCGC( AllTrim((cNextAlias)->A1_CGC ))

oCliente:SetCEP( AllTrim((cNextAlias)->A1_CEP ))

oCliente:SetEnd( AllTrim((cNextAlias) >A1 END ))


https://mvcadvpl.wordpress.com/category/rest/ 11/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
oCliente:SetEnd( AllTrim((cNextAlias)->A1_END ))

oCliente:SetDDD( AllTrim((cNextAlias)->A1_DDD ))

oCliente:SetTel( AllTrim((cNextAlias)->A1_TEL ))

oResponse:Add(oCliente)

(cNextAlias)->( DbSkip() )

EndDo

cJSON := FWJsonSerialize(oResponse, .T., .T.,,.F.)

::SetResponse(cJSON)

Else

SetRestFault(400, “SA1 Empty”)

lRet := .F.

EndIf

RestArea(aArea)

Return(lRet)

Explicação do trecho de código acima:

Como vimos na primeira postagem, para serialização de um objeto JSON, precisamos passar um
objeto para a função FWJSONSerialize, para isso nas linhas 5 e 6 temos a declaração de duas variáveis
que são objetos das classes CLIENTES e FULL_CLIENTES.

CLIENTES é onde armazenamos os atributos do cliente.


FULL_CLIENTES é onde armazenamos uma lista dos objetos da classe CLIENTES

Logo a seguir fazemos uma query na tabela de clientes (SA1).

Na linha 19 temos a condição (cNextAlias)->( !Eof() ) , nesse momento eu verifico se a minha query
retornou algum resultado.

Retorno da condicional positivo:

Caso tenha retornado então iremos alimentar os objetos como podemos ver o trecho de código entre
as linhas 21 e 35.

Entre as linhas 23 e 30 alimentamos o objeto oCliente com os dados do cliente.

Na linha 32 adicionamos o objeto cliente já alimentado, na lista de clientes oResponse pois será essa
lista que iremos serializar.

Após sair do loop onde alimentamos os objetos, utilizamos o seguinte comando para transformar a
nossa lista de clientes (oResponse) em uma string JSON serializada e na sequência utilizamos o
comando SetResponse para enviar a string ao cliente.

cJSON := FWJsonSerialize(oResponse T T F )
https://mvcadvpl.wordpress.com/category/rest/ 12/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
cJSON : FWJsonSerialize(oResponse, .T., .T.,,.F.)

::SetResponse(cJSON)

Retorno da condicional negativo:

Caso minha query não retorne nenhum registro então iremos utilizar a função SetRestFault para
retornar um código HTTP de erro e uma mensagem.

SetRestFault(400, “SA1 Empty”)

Exemplo de retorno com o resultado negativo da condicional (sem dados no SA1):

Exemplo de retorno com o resultado positivo da condicional (com dados no SA1):

POST:

O método POST é responsável por incluir ou processar algum tipo de informação enviada pelo client.

Vamos ver abaixo um exemplo de método post:

Iremos receber um JSON com dados de um cliente e realizar a inclusão do mesmo caso não exista na
base de dados.

Estrutura do JSON que vamos receber:

https://mvcadvpl.wordpress.com/category/rest/ 13/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

WSMETHOD POST WSRECEIVE RECEIVE WSSERVICE CLIENTES

Local cJSON := Self:GetContent() // Pega a string do JSON

Local oParseJSON := Nil

Local aDadosCli := {} //–> Array para ExecAuto do MATA030

Local cFileLog := “”

Local cJsonRet := “”

Local cArqLog := “”

Local cErro := “”

Local cCodSA1 := “”

Local lRet := .T.

Private lMsErroAuto := .F.

Private lMsHelpAuto := .F.

// –> Cria o diretório para salvar os arquivos de log

If !ExistDir(“\log_cli”)

MakeDir(“\log_cli”)

EndIf

// –> Deserializa a string JSON

FWJsonDeserialize(cJson, @oParseJSON)

SA1->( DbSetOrder(3) )

If !(SA1->( DbSeek( xFilial(“SA1”) + oParseJSON:CLIENTE:CGC ) ))

cCodSA1 := GetNewCod()

Aadd(aDadosCli {“A1 FILIAL” xFilial(“SA1”) Nil} )


https://mvcadvpl.wordpress.com/category/rest/ 14/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
Aadd(aDadosCli, { A1_FILIAL , xFilial( SA1 ) , Nil} )

Aadd(aDadosCli, {“A1_COD” , cCodSA1 , Nil} )

Aadd(aDadosCli, {“A1_LOJA” , “01” , Nil} )

Aadd(aDadosCli, {“A1_CGC” , oParseJSON:CLIENTE:CGC , Nil} )

Aadd(aDadosCli, {“A1_NOME” , oParseJSON:CLIENTE:NOME , Nil} )

Aadd(aDadosCli, {“A1_NREDUZ” , oParseJSON:CLIENTE:NOME , Nil} )

Aadd(aDadosCli, {“A1_END” , oParseJSON:CLIENTE:ENDERECO ,Nil}

Aadd(aDadosCli, {“A1_PESSOA” , Iif(Len(oParseJSON:CLIENTE:CGC)== 11, “F”, “J”) , Nil}


)
Aadd(aDadosCli, {“A1_CEP” , oParseJSON:CLIENTE:CEP , Nil} )

Aadd(aDadosCli, {“A1_TIPO” , “F” , Nil} )

Aadd(aDadosCli, {“A1_EST” , oParseJSON:CLIENTE:ESTADO , Nil} )

Aadd(aDadosCli, {“A1_MUN” , oParseJSON:CLIENTE:MUNICIPIO,Nil} )

Aadd(aDadosCli, {“A1_TEL” , oParseJSON:CLIENTE:TELEFONE, Nil} )

MsExecAuto({|x,y| MATA030(x,y)}, aDadosCli, 3)

If lMsErroAuto

cArqLog := oParseJSON:CLIENTE:CGC + ” – ” +SubStr(Time(),1,5 ) + “.log”

RollBackSX8()

cErro := MostraErro(“\log_cli”, cArqLog)

cErro := TrataErro(cErro) // –> Trata o erro para devolver para o client.

SetRestFault(400, cErro)

lRet := .F.

Else

ConfirmSX8()

cJSONRet := ‘{“cod_cli”:”‘ + SA1->A1_COD + ‘”‘;

+ ‘,”loja”:”‘ + SA1->A1_LOJA + ‘”‘;

+ ‘,”msg”:”‘ + “Sucesso” + ‘”‘;

+’}’

::SetResponse( cJSONRet )

EndIf

Else
https://mvcadvpl.wordpress.com/category/rest/ 15/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
Else

SetRestFault(400, “Cliente já cadastrado: ” + SA1->A1_COD + ” – ” + SA1->A1_LOJA)

lRet := .F.

EndIf

Return(lRet)

Explicação do trecho de código acima:

Linha 3 -> Pega o JSON recebido e armazena na variável cJson

Linha 19 -> Deserializa Json recebido utilizando a função FWJsonDeserialize e disponibiliza os dados
do mesmo no objeto oParseJSON.

Na linha 22 temos uma condicional que verifica se o CPF/CNPJ recebido já consta em nossa base de
dados.

Retorno Negativo da condicional:

Caso o CGC informado não exista na nossa base de dados, então vamos realizar a inclusão do cliente
usando ExecAuto.

Montamos o array e chamamos a função MsExecAuto.

Retorno para o Client:

Se no MsExecAuto der algum tipo de inconsistência então retornamos a mensagem de


inconsistência para o cliente utilizando a função SetRestFault como podemos ver na linha 51.
Caso contrário eu devolvo um JSON com o código e loja do cliente que acabou de ser incluído,
como podemos ver na linha 59.
Repare que na linha 59 eu estou utilizando o comando SetResponse utilizando uma string que
montei “na unha”, como podemos ver no seguinte trecho:

cJSONRet := ‘{“cod_cli”:”‘ + SA1->A1_COD + ‘”‘;

+ ‘,”loja”:”‘ + SA1->A1_LOJA + ‘”‘;

+ ‘,”msg”:”‘ + “Sucesso” + ‘”‘;

+’}’

Sim … Podemos montar o nosso JSON “na unha”, apesar de ser muito mais trabalhoso.

Exemplo de retorno com erro do execauto:

https://mvcadvpl.wordpress.com/category/rest/ 16/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

Exemplo de retorno com um cliente já existente na base de dados:

Exemplo de retorno com sucesso na inclusão de um cliente:

PUT:

O método PUT é responsável por alterar algum tipo de informação enviada pelo client.

Vamos ver abaixo um exemplo de método put:

Iremos receber um JSON com dados de um cliente e realizar a alteração do mesmo caso exista na base
de dados.
https://mvcadvpl.wordpress.com/category/rest/ 17/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

Neste exemplo teremos parâmetros recebidos via URL que no caso será o CGC (cpf ou cnpj) do cliente
que queremos realizar a alteração e o conteúdo via JSON que será recebido via POST-Request (no
corpo da requisição HTTP).

Estrutura da JSON que iremos receber:

WSMETHOD PUT WSRECEIVE RECEIVE WSSERVICE CLIENTES

Local cJSON := Self:GetContent() // –> Pega a string do JSON

Local cCGC := Self:CGC // –> Pega o parâmetro recebido pela URÇ

Local lRet := .T.

Local oParseJSON := Nil

Local aDadosCli := {} //–> Array para ExecAuto do MATA030

Local cJsonRet := “”

Local cArqLog := “”

Local cErro := “”

Private lMsErroAuto := .F.

If !ExistDir(“\log_cli”)

MakeDir(“\log_cli”)

EndIf

::SetContentType(“application/json”)

// –> Deserializa a string JSON

FWJsonDeserialize(cJson, @oParseJSON)

SA1->( DbSetOrder(3) )

If (SA1->( DbSeek( xFilial(“SA1”) + cCGC ) ))

Aadd( aDadosCli, {“A1_NOME”, oParseJSON:CLIENTE:NOME , Nil } )

Aadd( aDadosCli, {“A1_END” , oParseJSON:CLIENTE:ENDERECO , Nil } )

MsExecAuto({|x,y| MATA030(x,y)}, aDadosCli, 4)

If lMsErroAuto
https://mvcadvpl.wordpress.com/category/rest/ 18/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
If lMsErroAuto

cArqLog := oParseJSON:CLIENTE:CGC + ” – ” + SubStr( Time(),1,5 ) + “.log”

cErro := MostraErro(“\log_cli”, cArqLog)

cErro := TrataErro(cErro) // –> Trata o erro para devolver para o client.

SetRestFault(400, cErro)

lRet := .F.

Else

cJSONRet := ‘{“cod_cli”:”‘ + SA1->A1_COD + ‘”‘;

+ ‘,”loja”:”‘ + SA1->A1_LOJA + ‘”‘;

+ ‘,”msg”:”‘ + “Alterado” + ‘”‘;

+’}’

::SetResponse( cJSONRet )

EndIf

Else

SetRestFault(400, “Cliente não encontrado.”)

lRet := .F.

EndIf

Return(lRet)

O único ponto de atenção que deveremos ter nesse método é a linha 4, pois é ali que recebemos o CGC
do cliente informado através da URL no qual iremos modificar.

Todo o restante dos comandos, já está explicado nos métodos POST e GET.

Exemplo de requisição efetuada com sucesso:

https://mvcadvpl.wordpress.com/category/rest/ 19/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

Exemplo de requisição efetuada com erro:

Link do GitHub:

h ps://github.com/VctrAndrade/RestAdvplPost02
(h ps://github.com/VctrAndrade/RestAdvplPost02)

Bom pessoal, espero que gostem e nos envie sugestões também

Abraços!

Seu primeiro Webservice REST no ERP Protheus

16 16+00:00 ABRIL 16+00:00 201716 16+00:00 ABRIL 16+00:00 2017 ⁄ VICTOR ANDRADE ⁄ 16
COMENTÁRIOS
– 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 (h p://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol) (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
https://mvcadvpl.wordpress.com/category/rest/ 20/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
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.
REST é baseado no design do protocolo HTTP, que já possui diversos mecanismos embutidos para
representar recursos como código de status, representação de tipos de conteúdo, cabeçalhos, etc.

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” como diz a Ju rs.

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]
https://mvcadvpl.wordpress.com/category/rest/ 21/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
[ONSTART]

JOBS=HTTPJOB

REFRESHRATE=120

[HTTPJOB]

MAIN=HTTP_START

ENVIRONMENT=P12LOCAL

Habilitando o servidor HTTP para REST:

[HTTPV11]

Enable=1

Sockets=HTTPREST

Obs: A chave Sockets referencia a(s) seção(ões) com a configuração de porta e URL que a mesma irá
atender, permitindo que o Application Server seja configurado com mais de uma porta HTTP do REST:

[HTTPV11]

Enable=1

Sockets=HTTPREST,HTTPREST2

Configuração do(s) socket(s) definidos na seção HTTPV11:

[HTTPREST]

Port=8080

IPsBind=

URIs=HTTPURI

Security=0

Descrição
Parametro
Port Porta HTTP
IPsBind Indica os IPs que serão atendidos por essa porta, se não informado atenderá qualquer
IP / DNS associado ao servidor
URIs Seções com configuração de URL e ambiente (pelo menos uma seção)
Security Indica se a autenticação de requisição esta habilitada
Observação
O HTTP do REST verifica existência do campo Authorization no HEADER da requisição, porém a
t i ã é li d l f
https://mvcadvpl.wordpress.com/category/rest/
kd d t tá/ tili d t l 22/31
10/08/2020 REST | Desmistificando o MVC no AdvPL
autorização é realizada pelo framework do produto que está/ utilizando o protocolo
Para facilitar o desenvolvimento e testes pode-se configurar a chave Security com valor 0 (zero)
para desabilitar a autenticação

A chave URIs referência a(s) seção(ões) com a configuração da URL que a porta irá atender, permite
também que seja configurado com mais de uma URL:

[HTTPREST]

Port=8012

IPsBind=

URIs=HTTPURI,HTTPURI2

Security=1

Configuração da(s) seções URIs:

[HTTPURI]

URL=/rest

PrepareIn=99,01

Instances=1,1

Parametro Descrição
URL Indica o endereço que será atendido
Nesse exemplo h p://localhost:8012/rest (h p://localhost:8080/rest)
Preparein Informações de empresa e filial para preparação do ambiente das working threads
Instances Configuração de inicialização de working threads
CorsEnable Indica se habilita o CORS
Observaçoes
A chave CORS é utilizada para permitir que páginas WEB de diferentes domínio do qual o servidor
HTTP do Protheus está alocado, consigam realizar a requisição na nossa URI.
Essa parte configuração não temos muito como fugir do que está descrito no TDN, está bem
documentado por parte da TOTVS.

Após a configuração, o appserver.ini deverá ficar da seguinte maneira:

https://mvcadvpl.wordpress.com/category/rest/ 23/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

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 h p/rest:

https://mvcadvpl.wordpress.com/category/rest/ 24/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

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:

h p://localhost:8012/rest (h p://localhost:8012/rest)

Deverá ser exibida a seguinte tela:

https://mvcadvpl.wordpress.com/category/rest/ 25/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

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: Includes

Para 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'
#Include 'FWMVCDEF.ch'
#Include 'RestFul.CH'

User Function EREST_01()


Return

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 WebService

Para 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

https://mvcadvpl.wordpress.com/category/rest/ 26/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

END WSRESTFUL

Entendendo o trecho de código acima:

Linha 1:

WSRESTFUL -> Início da declaração da estrutura do Webservice;


PRODUTOS -> Nome do webservice
DESCRIPTION -> Descrição do serviço

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:

Float
Boolean
String
Array
Integer

Linha 5:

WSMETHOD -> Definição de um método


GET -> Define qual o tipo do método que estamos criando, podendo ser
GET
POST
UPDATE
DELETE
DESCRIPTION -> Descrição do método.
SYNTAX -> Sintaxe HTTP da chamada REST. Esta informação é utilizada na documentação do
REST.

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.

https://mvcadvpl.wordpress.com/category/rest/ 27/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

WSMETHOD GET WSRECEIVE CODPRODUTO WSSERVICE PRODUTOS


Local cCodProd := Self:CODPRODUTO
Local aArea := GetArea()
Local oObjProd := Nil
Local cStatus := ""
Local cJson := ""

::SetContentType("application/json")

DbSelectArea("SB1")
SB1->( DbSetOrder(1) )
If SB1->( DbSeek( xFilial("SB1") + cCodProd ) )
cStatus := Iif( SB1->B1_MSBLQL == "1", "Sim", "Nao" )
oObjProd := Produtos():New(SB1->B1_DESC, SB1->B1_UM, cStatus)
EndIf

cJson := FWJsonSerialize(oObjProd)

::SetResponse(cJson)

RestArea(aArea)
Return(.T.)

Entendendo o trecho de código acima:

Linha 1:

WsMethod -> Indica a iniciação de escrita do método


GET -> Tipo do método (Podendo ser GET, POST, UPDATE e DELETE).
WSRECEIVE -> Indica os parâmetros que iremos receber, no nosso caso, iremos receber o código
de produtos via URL (Request Get), mas poderíamos receber também um JSON Object (Request
POST).
WSSERVICE -> Indica o nome do webservice ao qual esse método pertence, no nosso caso o nome
é PRODUTOS.

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:
https://mvcadvpl.wordpress.com/category/rest/ 28/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

cCodProd -> Armazena o código do produto informado na URL.


oObjProd -> Classe que iremos criar para serializar o nosso json;

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.

Para mais informações acesse a documentação da função na TDN:

h p://tdn.totvs.com/display/public/mp/FWJsonSerialize+-
+Serializa+qualquer+tipo+de+dado+no+formato+JSON
(h p://tdn.totvs.com/display/public/mp/FWJsonSerialize+-
+Serializa+qualquer+tipo+de+dado+no+formato+JSON)

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:
https://mvcadvpl.wordpress.com/category/rest/ 29/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

Teste pelo Postman:

Teste pelo Navegador:

Esse é um exemplo muito simples do que podemos fazer com webservices REST, nos próximos Posts
vamos nos aprofundar cada vez mais.

Fontes no GitHub:

https://github.com/VctrAndrade/RestAdvplPost01

EREST_01.prw (https://github.com/VctrAndrade/RestAdvplPost01/blob/master/EREST_01

EREST_01A.prw (https://github.com/VctrAndrade/RestAdvplPost01/blob/master/EREST_0

—————————————————————————————————————————————-

Obrigado Galera e espero que tenham gostado.

Victor Andrade

Referências:

h p://www.matera.com/br/2012/10/22/como-funciona-um-webservice-rest/
(h p://www.matera.com/br/2012/10/22/como-funciona-um-webservice-rest/)

h p://tdn.totvs.com/display/home/TDN+-+TOTVS+Developer+Network
(h p://tdn.totvs.com/display/home/TDN+-+TOTVS+Developer+Network)

BLOG NO WORDPRESS.COM.
https://mvcadvpl.wordpress.com/category/rest/ 30/31
10/08/2020 REST | Desmistificando o MVC no AdvPL

https://mvcadvpl.wordpress.com/category/rest/ 31/31

Você também pode gostar