sábado, 11 de fevereiro de 2017

REST e Data Provider

Fechando o ciclo dos webservices do tipo REST falta ainda discutir um pouco a respeito da obtenção de uma lista de registros de um certo sistema, ou kb, para que possamos ter informação em nosso sistema cliente.

Em nossos artigos anteriores tratamos a respeito da metodologia para se desenvolver o CRUD utilizando uma transação: REST & SOAP, porém este modelo nos permite atuar sobre determinado registro apenas. Discutimos inclusive a importância de se estabelecer um mecanismo de segurança, que optamos pelo GAM pela praticidade e recursos. O último tratou de uma ferramenta de apoio para que possamos testar o serviço remotamente, REST client. O que falta agora é discutir como acessar informações no servidor, trazendo uma coleção de registros ao mesmo tempo.

Data Provider

Este recurso está passando por algumas transformações importantes, e desde o seu nascimento, a então Artech já dava as premissas de uma revolução no modelo de programação com seu descreva ao invés de programar.

Creio que a grande maioria dos genexandos já se depararam com este objeto, talvez apenas não avançaram para torná-lo um serviço REST, então vamos dedicar alguns parágrafos para explicá-lo. O Wiki Genexus traz muito boas informações sobre este tema.

1) Começamos montando um SDT 

Criar um SDT com a estrutura da informação desejada é o primeiro passo para exportarmos informação. E aqui vale inclusive arrastar a transação para o editor de SDT para que este inclua todos os campos desta no objeto que estamos construindo.

Seguindo a linha dos exemplos anteriores, vamos gerar uma lista de empresas a partir da transação Empresa. O SDT é o mesmo do exemplo em REST & SOAP


2) Criando o Data Provider

O próximo passo é arrastar o SDT para dentro do objeto Data Provider. Se encontrar alguma dificuldade para remover as atribuições padrões do Genexus temos aqui a solução Krueger.



A aplicação de filtros where é permitida, e neste caso teremos que enviar parâmetros para o serviço REST. Não esqueça de incluir uma regra Parm com os parâmetros

parm(&EmpresaId);

3) Definindo as propriedades do DP

Além de definir o Output como Collection=true, também será necessário expor o objeto como Serviço REST.



4) Montando o cliente

Uma segunda KB ou qualquer programa externo poderá consultar nosso DP REST, e claro, mantendo o mesmo esquema de proteção do GAM, o cliente deverá realizar primeiramente o login, para em seguida poder executar o DP. Uma chamada ao serviço /oauth, passando-se os parâmetros corretos, realiza a proposta. Como informamos no artigo anterior o client_id é obtido no GamHome.

sub 'login'
 &httpclient.Host = 'localhost/'
 &httpclient.Port = 80
 &httpclient.BaseUrl = '/Kb.NetEnvironment/oauth/'
 &addstring ='client_id=068868de058b4798bd3b90f696fa37f8&grant_type=password&scope=FullControl&username=admin&password=admin123'
 &httpclient.AddHeader("Content-Type", "application/x-www-form-urlencoded")
 &httpclient.AddString(&addstring)
 &httpclient.Execute('POST','access_token')
 &AccessTokenSDT.FromJson(&httpclient.ToString())
 &websession.set('TOKEN', &AccessTokenSDT.access_token)
EndSub

Para completar o processo de login e necessário obter o token, e para isto programamos o AccessTokenSDT que formata a respota do GAM. Se estivermos tratando de Genexus para Genexus, os objetos podem ser exportados e importados na Kb cliente, porém, para outros ambientes teremos que definir, na linguagem específica a respectiva estrutura.


Armazenamos o Token na sessão para poder acessar seu valor quando necessário.


&websession.set('TOKEN', &AccessTokenSDT.access_token)

A chamada ao Data Provider deve ser realizado passando-se o token.

&httpclient.AddHeader('Authorization','OAuth ' + &websession.get('TOKEN'))

Em seguida uma variável querystring é programada para informar o parâmetro a ser passado. Observe que o parametro deve ser declarado neste modelo, "?EmpresaId=" + trim(&EmpresaId.ToString()). O Data Provider é incluído no querystringempresadp.

&querystring='empresadp' + "?EmpresaId=" + trim(&EmpresaId.ToString())

O código completo da chamada é apresentado a seguir.

Event Enter
do 'login'

&httpclient.Host = 'localhost/'
&httpclient.Port = 80
&httpclient.BaseUrl = '/Kb.NetEnvironment/rest/'
&httpclient.AddHeader('content-type','application/json')
&httpclient.AddHeader('Authorization','OAuth ' + &websession.get('TOKEN'))
&querystring='empresadp' + "?EmpresaId=" + trim(&EmpresaId.ToString())
&httpclient.Execute('GET', &querystring)
&resposta = &httpclient.ToString()
Endevent

Para transformar a resposta em uma variável SDT é possível desde que definido. Fizemos isto no primeiro passo, ao criar o EmpresaSDT. Será necessário é transferir o objeto da Kb onde se encontra o Data Provider para a Kb cliente.


Uma variável do tipo EmpresaSDT deve ser criada como Collection=true. E, em seguida, um FromJson resolverá a parada.

&EmpresaSDT.FromJson(&httpclient.ToString())

O resultado disso? temos os registros recuperados da tabela Empresa, filtrados pela variável &EmpresaSDT. Desta forma podemos 'consultar' esta tabela em memória, na máquina cliente.

Fechando a conta

Temos muitos recursos interessantes que poderemos utilizar para solucionar nossos problemas de programação. O uso de webservices é importante porque toda lógica de proteção dos dados se encontra sob o domínio da Kb que fornece o serviço. Diferentemente de um acesso direto à tabela, por meio de um DataView, os webservices permitem um maior controle sobre o acesso e autorizações sobre as operações que cada sistema cliente terá.

Talvez não sirva para todas as situações, mas com certeza, para cenários de multiplos sistemas que necessitam trocar informações é uma excelente aposta.

Maiores informações:
Acesso aos exemplos, formato XPZ:
Gerador:
  • .Net a chamada ao serviço REST não precisa obedecer rigorosamente o nome do DP, podendo ser utilizado letras maiusculas ou minúsculas
  • Java exige que o nome do serviço obedeça o case das fontes.