Hoje vamos demonstrar a diferença entre o REST clássico com WSRestFul e o novo utilizando Annotation.
Para quem já desenvolveu WebServices em AdvPL, sabe que para utilizarmos REST, tínhamos que fazer usando WSRestFul. Mas com a vinda do TL++, nós podemos fazer de modo mais simples com Annotation.
Além das configurações no .ini (no fim desse artigo vou deixar um link de referência do TDN), as diferenças estão na estrutura das funcionalidades, enquanto no WSRestFul, segue uma estrutura parecida com Classe, na nova, é usada uma estrutura de função com User Function.
Eu montei um pequeno exemplo de GET em ambos os casos.
Abaixo o exemplo com WSRestFul, fonte WSGrupoProdAnt.prw:
//Bibliotecas
#Include "Totvs.ch"
#Include "RESTFul.ch"
#Include "TopConn.ch"
/*/{Protheus.doc} WSRESTFUL WSGrupoProdAnt
WS Grupo de Produtos
@author Atilio
@since 02/10/2022
@version 1.0
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
WSRESTFUL WSGrupoProdAnt DESCRIPTION 'WS Grupo de Produtos'
//Atributos
WSDATA id AS STRING
//Métodos
WSMETHOD GET ID DESCRIPTION 'Retorna o registro pesquisado' WSSYNTAX '/WSGrupoProdAnt/get_id?{id}' PATH 'get_id' PRODUCES APPLICATION_JSON
END WSRESTFUL
/*/{Protheus.doc} WSMETHOD GET ID
Busca registro via ID
@author Atilio
@since 02/10/2022
@version 1.0
@param id, Caractere, String que será pesquisada através do MsSeek
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
WSMETHOD GET ID WSRECEIVE id WSSERVICE WSGrupoProdAnt
Local lRet := .T.
Local jResponse := JsonObject():New()
Local cAliasWS := 'SBM'
//Se o id estiver vazio
If Empty(::id)
//SetRestFault(500, 'Falha ao consultar o registro') //caso queira usar esse comando, você não poderá usar outros retornos, como os abaixo
Self:setStatus(500)
jResponse['errorId'] := 'ID001'
jResponse['error'] := 'ID vazio'
jResponse['solution'] := 'Informe o ID'
Else
DbSelectArea(cAliasWS)
(cAliasWS)->(DbSetOrder(1))
//Se não encontrar o registro
If ! (cAliasWS)->(MsSeek(FWxFilial(cAliasWS) + ::id))
//SetRestFault(500, 'Falha ao consultar ID') //caso queira usar esse comando, você não poderá usar outros retornos, como os abaixo
Self:setStatus(500)
jResponse['errorId'] := 'ID002'
jResponse['error'] := 'ID não encontrado'
jResponse['solution'] := 'Código ID não encontrado na tabela ' + cAliasWS + ', informe outro código'
Else
//Define o retorno
jResponse['grupo'] := (cAliasWS)->BM_GRUPO
jResponse['desc'] := (cAliasWS)->BM_DESC
EndIf
EndIf
//Define o retorno
Self:SetContentType('application/json')
Self:SetResponse(jResponse:toJSON())
Return lRet
Abaixo o exemplo com Annotation, fonte WSGrupoProdNov.tlpp:
//Bibliotecas
#Include "Tlpp-Core.th"
#Include "Tlpp-Rest.th"
/*/{Protheus.doc} User Function WSGrupoProdNovGetUnico
Exemplo de WS para buscar um grupo de produto conforme código
@type Function
@author Atilio
@since 02/10/2022
/*/
@Get("WsGrupoProdNov/get/unico/")
User Function WSGrupoProdNovGetUnico()
Local jResponse := JsonObject():New() As Json
Local jPath As Json
Local cAliasWS := 'SBM' As Character
//Busca os dados que o usuário informou
jPath := JsonObject():New()
jPath := oRest:getQueryRequest()
//Caso haja conteúdo e não esteja vazio o ID
If jPath != Nil .And. ! Empty(jPath:GetJsonObject('id'))
DbSelectArea(cAliasWS)
(cAliasWS)->(DbSetOrder(1))
//Se não encontrar o registro
If ! (cAliasWS)->(MsSeek(FWxFilial(cAliasWS) + jPath:GetJsonObject('id') ))
oRest:setStatusCode(500)
jResponse['errorId'] := 'ID002'
jResponse['error'] := 'ID não encontrado'
jResponse['solution'] := 'Código ID não encontrado na tabela ' + cAliasWS + ', informe outro código'
//Define o retorno
Else
jResponse['grupo'] := (cAliasWS)->BM_GRUPO
jResponse['desc'] := (cAliasWS)->BM_DESC
EndIf
//Do contrário, irá retornar uma mensagem que não foi encontrado
Else
oRest:setStatusCode(500)
jResponse['errorId'] := 'ID001'
jResponse['error'] := 'ID vazio'
jResponse['solution'] := 'Informe o ID'
EndIf
//Encerra retornando o JSON
oRest:setKeyHeaderResponse('Content-Type','application/json')
oRest:setResponse(jResponse:toJSON())
Return
Referências:
- Configuração completa do novo REST no AppServer
- REST server (tlppCore) – TDN
- Migração WsRESTful para REST tlppCore
Bom pessoal, por hoje é só.
Abraços e até a próxima.