Paginação de API com OpenEdge
Figure: REST API - Author: Seobility - License: CC BY-SA 4.0

Paginação de API com OpenEdge

É mais do que conhecida a importância de enviar registros em lotes do servidor para o cliente por meio de APIs. Uma das vantagens é um menor tempo de espera por parte do cliente enquanto carrega os dados, menor tráfico de dados desnecessários saindo do servidor, além de que é uma boa prática.

Não sou a melhor pessoa para explicar o que é uma API com paginação, nem o porquê você deveria adotar esta prática. O objetivo aqui é mostrar uma maneira de fazer isso usando Progress OpenEdge e Progress Application Server for OpenEdge (PASOE ou OEPAS).

Se você conhece uma maneira diferente de paginar suas APIs com Progress OpenEdge , compartilhe nos comentários! E antes de ir aos códigos, é válido mencionar o curso gratuito da Progress para se tornar um desenvolvedor OpenEdge, confira!



Antes do código

Neste artigo não entrarei em detalhes sobre configuração da IDE PDSOE, nem sobre criar um projeto server. Neste momento meu PDSOE já está configurado com uma conexão ao banco de dados sports2020, e um projeto OpenEdge com server e REST transport for PASOE, chamado ws.

O exemplo para a paginação da API é retornar registros da tabela item com um limite máximo de 200 registros por requisição, e opção de apontar o id para o próximo lote de registros. Ambos passados como parâmetros na URL do endpoint.

Seções do artigo:

  1. Código (o arquivo .p)
  2. Mapeando o .p como um endpoint
  3. Testando o endpoint em uma instância local PASOE


1. Código (o arquivo .p)

Começo definindo os objetos, como temp-table, datasource, dataset, e query:

DEFINE TEMP-TABLE ttItem NO-UND
    FIELD ItemNum    LIKE Item.ItemNum 
    FIELD ItemName   LIKE Item.ItemName 
    FIELD Price      LIKE Item.Price 
    INDEX ItemNum IS PRIMARY IS UNIQUE ItemNum.
    
DEFINE DATA-SOURCE srcItem FOR Item.
DEFINE DATASET dsItem FOR ttItem.
DEFINE QUERY qItem FOR ttItem.        

Em seguida, os parâmetros de INPUT e OUTPUT. Estes parâmetros serão usados na definição do endpoint no REST Resource URI Editor.

DEFINE INPUT PARAM              iQty    AS INTEGER   NO-UNDO
DEFINE INPUT-OUTPUT PARAM       pRowId  AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAM             cStatus AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAM DATASET FOR dsItem.        

O bloco principal, com toda a lógica e comentários em cada etapa:

/* Limpa o dataset */
DATASET dsItem:EMPTY-DATASET ().

/* Validações iniciais */
IF iQty = 0 THEN RETURN.
IF iQty > 200 THEN
DO:
    ASSIGN
        cStatus = "Not alowed! Maximum of 200 records per request!".
    RETURN.
END.

ASSIGN
    cStatus = "Unknown error!".

/* Vincula o datasource srcItem ao buffer ttItem */
BUFFER ttItem:ATTACH-DATA-SOURCE(DATA-SOURCE srcItem:HANDLE).

/* Configur o RESTART-ROWID usando o pRowId informado */
IF LENGTH(pRowId) > 0 THEN
  DATA-SOURCE srcItem:RESTART-ROWID = TO-ROWID(pRowId).

/* Configura quantidade de registros por lote */
BUFFER ttItem:BATCH-SIZE = iQty.

/* Limpa a tabela antes da operação FILL (preencher) iniciar */
BUFFER ttItem:FILL-MODE = "EMPTY".

/* Preenche dataset */
DATASET dsItem:FILL().

/* Obtém próximo NEXT-ROWID do DATA-SOURCE para retornar */
pRowId = STRING(DATA-SOURCE srcItem:NEXT-ROWID).

/* Desvincula o datasource */
BUFFER ttItem:DETACH-DATA-SOURCE().

ASSIGN
    cStatus = "Success!".        

Adicionando o CATCH usando Progress.Lang.Error, para capturar qualquer condição não esperada ocorrida durante a execução:

CATCH err AS Progress.Lang.Error 
    DEFINE VARIABLE iMessage AS INTEGER NO-UNDO.
    
    DO WHILE iMessage < err:NumMessages:
        ASSIGN 
            cStatus = SUBSTITUTE ("&1~n&2", cStatus, err:GetMessage(iMessage))
            iMessage = iMessage + 1.
    END.
    IF err:CallStack <> ? THEN DO:
        ASSIGN 
            cStatus = SUBSTITUTE ("&1~n~nCall Stack:~n&2", cStatus, err:CallStack).
    END.
END CATCH.:        

O código completo você pode encontrar aqui.

Uma vez que o código está pronto, o próximo passo é mapear o programa (.p) como um endpoint no REST Resource URI Editor.



2. Mapeando o .p como um endpoint

No REST Resource URI Editor você pode adicionar um novo recurso (endpoint) e associar os programas aos verbos (GET, PUT, POST e DELETE).

Criei um novo endpoint (chamado item), e selecionei o arquivo item.p para ser vinculado ao verbo GET:

No alt text provided for this image
Vinculando o programa com o verbo no REST Resource URI Editor

Então fiz a vinculação dos parâmetros de entrada (input) como Query String Parameters, os parâmetros que serão informados na URL do endpoint:

No alt text provided for this image
Vinculando parâmetros de entrada

Finalmente, vinculei os parâmetros de saída (output) ao Response Body:

No alt text provided for this image
Vinculando parâmetros de saída

Como já tenho uma instância do PASOE rodando localmente, e o projeto já está publicado no OpenEdge Explorer, a próxima etapa é testar o endpoint.



3. Testando o endpoint em uma instância local PASOE

Testando o limite de registros chamando http://localhost:8810/ws/rest/wsService/item?iQty=300:

No alt text provided for this image

Ótimo! A primeira validação executou com sucesso!


Agora, testando com limite de 3 registros em duas etapas:

Primeiro, chamando o endpoint sem passar o parâmetro pRowId, o que deve resultar nos três primeiros registros da tabela (http://localhost:8810/ws/rest/wsService/item?iQty=3).

E em seguida, passando o pRowId, obtido da requisição anterior, como parâmetro para a próxima requisição (http://localhost:8810/ws/rest/wsService/item?iQty=3&pRowId=0x0000000000005c04)

Veja os resultados abaixo:

No alt text provided for this image
Testando com limite de registros aceitável e passando pRowId para obter a próxima paginação

Ótimo! Tudo funcionou como esperado! Enquanto o artigo foca em um simples e específico escopo, existem muitas possibilidades de melhorias futuras e validações.


Se você estiver interessado em explorar o código completo, você pode encontrá-lo clicando aqui.

Espero que tenha gostado! Comente se isso é uma novidade para você ou se você desenvolve paginações em suas APIs de uma maneira diferente!


Sandra Takao

IT Projects | Digital Transformation |IT Leader| ERP | TOTVS Datasul | Salesforce | Field Service| 1x Certified Salesforce| AWS Certified | Microsoft Certified|

1 a

Sensacional Lucas. Tks por compartilhar

Entre para ver ou adicionar um comentário

Outras pessoas também visualizaram

Conferir tópicos