Quero passar o objeto JSON de uma service para a minha controller, tentei `cResponseJson := SolicitacaoArmazem:get()` mas não deu certo

Olá, boa tarde.

Estou aprendendo TLPP aqui e estou tentando jogar um JSON de uma Service para a minha Controller. Eu fiz da seguinte forma, primeiro, defini a Controller que criou a API com sucesso, e está recebendo os argumentos do REQUEST como deveria (Tirei partes que acho que não é necessário p/ entendimento):


Method get() as Logical Class SolicitacaoArmazemController

    // Setar Empresa e Filial no começo do App (Necessário)
    rpcSetEnv(cEmpAnt, cFilAnt)

    ConOut("SolicitacaoArmazemController:get - Coletando os Parametros da Query e do JSON Body")

    // Etc

    // Simular o jResponse (O JSON que tem na Classe) pra simular a resposta.
    // Inicialmente, trago da Service para testes e entendimento da arquitetura.
    Local cResponseJson as Json

    // Etc

    // Retornar um JSON criado pela Service
    cResponseJson := SolicitacaoArmazem:get()

    cTesteChegouAqui := "Sim ou não?"

    ConOut("SolicitacaoArmazemController:get - Configurando os Headers e a Response")
    oRest:setKeyHeaderResponse('Content-Type', 'application/json; charset=utf-8')    
    oRest:setResponse(cResponseJson)

    // Resetar a Empresa/Filial e liberar licenças utilizadas.
    rpcClearEnv()

Return .T.

E ai na minha Service eu crio um JSON pra testes, que eu passo para a minha Controller:


class SolicitacaoArmazemService
    Public Data jResponse as Json

    Public method new() as Object
    Public method get() as Json
EndClass

Method new() as Object Class SolicitacaoArmazemService
    ConOut("SolicitacaoArmazemService:new - Construindo a Service e instanciando JsonObject...")
    ::jResponse := JsonObject():New()
Return Self

Method get() as Json Class SolicitacaoArmazemService
    Local jResponse := '[{"Mensagem":"Hello World!"}]'
Return ::jResponse

Porém, ele não vai pra frente na linha cResponseJson := SolicitacaoArmazem:get().

Informações adicionais:

No Debug, ele quando chega na linha em questão tem o cResponseJson definido como Nil, e na linha seguinte ele para de executar e não preenche o cTesteChegouAqui. Vejam a imagem:

Imagem mostrando que não chegou no cTesteChegouAqui

:warning: Atenção: Esta publicação foi transferida automaticamente do fórum antigo, mas os anexos não foram incluídos.

1 curtida

Raul,

Seu código tem alguns problemas:

  • Você está abrindo o ambiente para cada requisição? Isso vai gerar uma lentidão IMENSA na sua API e seria impossível manter isso de pé em produção caso seja uma API muito utilizada:

    
    rpcSetEnv(cEmpAnt, cFilAnt)
    
    
  • A primeira coisa que deve ser feita em ADVPL/TLPP é declarar as variáveis, então fico na dúvida, isso está compilando? Pois você declara a variável após abrir o ambiente e fazer um conout:

    
    Local cResponseJson as Json
    
    
  • Quando um método da classe é chamado a primeira vez, ele cria uma instancia da classe, por padrão, damos o nome de new a esse método, mas isso não é uma regra, qualquer método da classe ao ser invocado pela primeira vez é o construtor, logo esse código, está devolvendo um objeto:

    
    cResponseJson := SolicitacaoArmazem:get()
    
    
  • Na classe SolicitacaoArmazem, método get, você coloca um valor de character na variável jResponde e não faz nada com ele, você acaba retornando a propriedade jResponse da classe, que pode estar nulo ou com um JSON vazio:

    
     Local jResponse := '[{"Mensagem":"Hello World!"}]'
    Return ::jResponse
    
    

Obs.: Para chamar um método sem instanciar a classe, você precisa declarar o método como estático, mas isso muda o comportamento, ele passa a ser um método da classe e não do objeto.


Para corrigir essa situação, poderia ser feito algo nessa linha de raciocínio:

Controller:


Method get() as Logical Class SolicitacaoArmazemController
    Local jResponseJson as Json
    Local oService as object

    //TODO: Precisa mesmo abrir o ambiente, ainda mais com as variáveis públicas cEmpAnt e cFilAnt? Não acaba ficando exatamente a mesma coisa? Veja mais na configuração do REST para já deixar o ambiente aberto e evitar isso
    rpcSetEnv(cEmpAnt, cFilAnt)

    ConOut("SolicitacaoArmazemController:get - Coletando os Parametros da Query e do JSON Body")

    oService := SolicitacaoArmazem():new()
    jResponseJson  := oService:get()

    cTesteChegouAqui := "Sim ou não?"

    ConOut("SolicitacaoArmazemController:get - Configurando os Headers e a Response")
    oRest:setKeyHeaderResponse('Content-Type', 'application/json; charset=utf-8')    
    oRest:setResponse(jResponseJson)

    //TODO: Se remover o RpcSetEnv, remover essa chamada também
    rpcClearEnv()

Return .T.

Service:


class SolicitacaoArmazemService
    Public Data jResponse as Json

    Public method new() as Object
    Public method get() as Json
EndClass

Method new() as Object Class SolicitacaoArmazemService
    ConOut("SolicitacaoArmazemService:new - Construindo a Service e instanciando JsonObject...")
    ::jResponse := JsonObject():New()
Return Self

Method get() as Json Class SolicitacaoArmazemService
    ::jResponse:fromJson('[{"Mensagem":"Hello World!"}]')
Return ::jResponse

Show. Obrigado Daniel, fez sentido agora! Eu não estava entendendo a lógica ali de como funcionava a parte de instanciar a classe e como eu fazia isso no método GET ali da classe… Sobre o ambiente da empresa, obrigado. Eu não sabia disso, vou configurar no AppServer lá pra sempre deixar aberto já na empresa certa. Testei aqui e deu certinho. Thanks!