Resposta rápida
- O que é
- a mesma linguagem TLPP usada para expor um endpoint HTTP, em vez de montar uma tela MVC — a diferença central é uma annotation sobre o método, não um servidor novo.
- As duas gerações
- convivem. WSRESTFUL em AdvPL continua presente em boa parte do padrão; a annotation TLPP já é a forma preferida para serviço novo.
- O que o TLPP acrescenta
namespace, tipagemas <Tipo>e um objetooRestinjetado no escopo, sem declaração.- Armadilha de quem vem de outra linguagem
String,Boolean,FloateVarcharnão são tipos do TLPP — éCharacter,LogicaleNumeric.- Este artigo
- compara as duas gerações. Os próximos descem para a annotation, o
oRest, os verbos e os erros.
Nesta página6 seções
A série sobre MVC já mostrou que o padrão continua montando tela em AdvPL,
com FWFormView():New, e não migrou esse desenho para o TLPP. Em API REST a
fotografia é o oposto: a TOTVS já escreve serviço novo em TLPP como prática
corrente — só que sem apagar o que existia antes. Vale comparar os dois lados
antes de tratar um como sucessor do outro.
As duas gerações convivem, lado a lado
WSRESTFUL, com WSMETHOD e WSDATA, ainda descreve boa parte do serviço
REST escrito em AdvPL — não foi removido, nem substituído de uma vez. A
annotation de verbo, em TLPP, cresce por cima disso: é a forma que a TOTVS
usa para escrever API nova, não para trocar a antiga. As duas sintaxes
não se misturam dentro do mesmo objeto — é a distinção que a próxima seção
detalha, porque confundi-las é o erro mais fácil de cometer numa migração.
Um nome não muda o servidor, muda o acesso ao contexto
Dentro de uma classe com annotation, o acesso ao objeto de requisição é
sempre oRest:, nunca ::. E o contrário nunca acontece: ::SetResponse
existe, mas só em fontes que ainda usam WSRESTFUL — nenhum deles tem
annotation. Não é que :: seja do modelo antigo: ele é só um apelido de
Self:, sintaxe corrente de orientação a objeto no TLPP, usada em qualquer
classe, com ou sem annotation. O que muda é para onde ele aponta, e o
próximo artigo da série detalha isso método a método.
oRest não é declarado: não há Local oRest, Public oRest nem
oRest := em nenhum controller que o usa. Ele simplesmente existe dentro do
corpo do método anotado — é injetado pelo runtime do compilador, não por
herança de classe.
Namespace e tipagem: o que o TLPP acrescenta de fato
Toda API nova em TLPP tende a declarar namespace, e boa parte importa
outro com using namespace. Não é decoração: é como uma classe de serviço
referencia uma classe de outra camada sem repetir o caminho inteiro do
identificador.
A tipagem as <Tipo> é o outro acréscimo real, e ela custa uma armadilha
específica para quem chega de outra linguagem. Os tipos que o TLPP
reconhece de fato são Object, Character, Numeric, Array, Logical,
Json e Date — não String, Boolean, Float, Varchar nem
DateTime. Quem os tenta por hábito de outra linguagem não recebe um erro
amigável, só um tipo que não existe.
public method listar() as logical
Method listar() Class FornecedoresApi
local jResposta := JsonObject():New() as json
local cFiltro := "" as character
Return .T.Vale o aviso, porque ele engana: AS VARCHAR aparece com frequência em
código real do Protheus, só que quase sempre dentro de SQL embutido em
string (CAST(... AS VARCHAR( 23 ) )) ou na cláusula WSDATA de um
WebService AdvPL clássico — nada disso é tipagem TLPP. O que importa é a
linha de declaração de tipo de um parâmetro ou retorno, não qualquer
ocorrência solta da palavra.
A tipagem do retorno de um método anotado também tem um padrão claro:
as logical é, disparado, a mais comum — mais frequente do que as variant e as object somados. as json, tipando o retorno pelo formato
que ele de fato devolve, é raridade. Quem tipa o retorno como o JSON que
devolve está sozinho.
JsonObject mora nessa mesma família, como tipo nativo (as json), e a
instanciação convive nas duas caixas — JsonObject():New() e
JsonObject():new() — sem que uma seja mais correta que a outra. A
linguagem é insensível a caixa, e o hábito de quem escreve não converge
para uma forma só.
Os includes existem — o cabeçalho, não
Todo fonte de API em TLPP inclui tlpp-core.th e, quando expõe rota,
também tlpp-rest.th. Só existe um punhado de includes tlpp-*.th na
linguagem inteira, e nenhum .prw/.prx inclui algum deles — é uma
fronteira real entre as duas gerações, não só de sintaxe.
try/catch existe, mas é minoria — e a grafia trai quem vem de outra linguagem
O bloco de tratamento de erro do TLPP fecha com endtry, colado, sem
espaço — end try, com espaço, simplesmente não existe na linguagem. E
catch não usa parênteses: é catch oError, com a variável ao lado.
try
self:runDiagnosis()
oRest:setResponse(self:cResponseBody)
catch oError
SetRestFault(500, FWHttpEncode(oError:description), .T.)
finally
self:finish()
endtryVale considerar isso antes de vender try/catch como o jeito consolidado
de tratar erro numa API: a maior parte do código real de tratamento de
erro em Protheus, incluindo fonte recente, ainda resolve com o
ErrorBlock() clássico do AdvPL. try/catch é o caminho certo para uma
API que precisa devolver um status HTTP previsível, mas apresentá-lo como
prática já consolidada seria enganar quem está aprendendo.
O que vem a seguir
Este artigo comparou as duas gerações. Os próximos descem peça por peça: a
annotation e as formas reais de escrever uma rota; o objeto oRest método a
método, com o que ele recebe e devolve; o primeiro @Get funcionando; como
tratar erro sem devolver sempre 500; os query e path params; a paginação com
FWAdapterBaseV2; o POST/PUT/DELETE gravando de verdade; e o que muda
quando a API precisa responder por mais de uma empresa. Quem ainda não tem a
base de MVC pode revisar antes
o que é e por que ele existe.
Se sua equipe está decidindo entre manter WSRESTFUL ou migrar para annotation em TLPP, fale com a gente.
Referências
TDNtdn.totvs.com
TDN — Migração WsRESTful para REST tlppCoreTDN devolve 403 sem login na consulta direta.TDNtdn.totvs.com
TDN — REST (TOTVSTEC)TDNtdn.totvs.com
TDN — Entendendo as novidades do RESTIndicada pelo catálogo como visão geral da annotation.
Continue por aqui
- Vídeo
ProtheusReferência técnica
O objeto oRest: como a requisição entra e a resposta sai
oRest não é declarado: a annotation REST do TLPP o injeta. Os métodos reais, o homônimo perigoso e por que na classe é oRest:, nunca ::.
- Vídeo
ProtheusTutorial
API GET: a listagem e o detalhe de um registro
GET de listagem devolve um resumo por SQL; GET de detalhe busca o registro inteiro por DbSeek pela chave do path. A armadilha do DbSeek de largura fixa.