Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

...

  • Através do método SimpleInput, a classe irá disponibilizar uma lista com os elementos que serão definidos na mensagem SOAP que será enviada. A lista possui o nome dos elementos e o id interno deles. Logo, para definir o valor de um elemento utiliza-se o id do mesmo. Mas é possível também definir o valor passando o nome do elemento, fazendo com que a classe procure o mesmo, seja o primeiro encontrado (métodos SetFirst ou SetFirstArray) ou de acordo com os elementos pai (métodos SetValPar ou SetValParArray), e defina seu valor.
  • WSDL - Web Services Description Language (Linguagem para descrição de web services) é uma linguagem baseada em XML para descrição dos serviços, operações e métodos de um web service. O documento gerado a partir do documento WSDL é no formato SOAP. Para mais informações sobre WSDL acesse o endereço: http://www.w3.org/TR/wsdl.
  • SOAP - Simple Object Access Protocol (Protocolo Simples de Acesso a Objetos) é um protocolo baseado em XML para troca de informações estruturadas em plataforma descentralizada e distribuída, normalmente web services. Para mais informações acesse: http://www.w3.org/TR/soap/.
  • Para obter mais informações dos modelos regulamentados pela W3C - World Wide Web Consortium, acesso o endereço: http://www.w3c.org.
  • Alguns endereços com tutoriais sobre as tecnologias envolvidas podem ser acessados em http://www.w3schools.com/ e http://www.tutorialspoint.com/.

Exemplos

Exemplo 1.A - Cria um WebService Agenda com elementos complexos

Bloco de código
languagecpp
themeEclipse
linenumberstrue
collapsefalse
#include "protheus.ch"
#include "apwebsrv.ch"
 
WSSTRUCT Contato
  WSDATA Nome AS String
  WSDATA Telefone AS String OPTIONAL
ENDWSSTRUCT
 
WSSTRUCT Contatos
  WSDATA Registros AS ARRAY OF Contato
ENDWSSTRUCT
 
WSSERVICE Agenda
  WSDATA _status AS Boolean
  WSDATA _dados AS Contatos
  WSMETHOD InsereContatos
  WSMETHOD ListaContatos
ENDWSSERVICE
 
WSMETHOD InsereContatos WSRECEIVE _dados WSSEND _status WSSERVICE Agenda
  Local nI

  // Exibe os dados recebidos. Eles seriam inseridos em um tabela num banco de dados.
  for nI := 1 to Len( ::_dados:Registros )
    conout( "Registro " + cValToChar( nI ) )
    conout( "Nome: " + ::_dados:Registros[nI]:Nome )
    conout( "Telefone: " + IIf( Empty( ::_dados:Registros[nI]:Telefone ), "Nao tem", ::_dados:Registros[nI]:Telefone ) + CRLF )
  next nI
   
  // Devove um status informando que a operação foi feita com sucesso. Esse status será devolvido na mensagem SOAP de resposta a esse método.
  ::_status := .T.
   
// Retorna que a operação foi feita com sucesso para a camada do Protheus. 
Return .T.
 
WSMETHOD ListaContatos WSRECEIVE NULLPARAM WSSEND _dados WSSERVICE Agenda
  Local nDay := dow( date() )
  Local oNewContato

  if nDay == 1 .Or. nDay == 7
    SetSoapFault( "Metodo não disponível", "Este serviço não funciona no fim de semana." )
     
    return .F.
  endif
   
  // Os dados de retorno seriam pegos do banco de dados.
  // Para esse exemplo iremos popular o retorno com dados fixos.
   
  // Cria a instância de retorno ( WSDATA _dados AS Contatos )
  ::_dados := WSClassNew( "Contatos" )
   
  // inicializa a propriedade da estrutura de retorno
  // WSDATA Registros AS ARRAY OF Contato
   
  ::_dados:Registros := {}
   
  // Cria e alimenta uma nova instancia do Contato
  oNewContato :=  WSClassNew( "Contato" )
  oNewContato:Nome := "Fulano"
  oNewContato:Telefone := "98765"
  AAdd( ::_dados:Registros, oNewContato )
   
  // Cria e alimenta uma nova instancia do Contato
  oNewContato :=  WSClassNew( "Contato" )
  oNewContato:Nome := "Ciclano"
  oNewContato:Telefone := "95678"
  AAdd( ::_dados:Registros, oNewContato )

  varInfo("listaContatos", ::_dados:Registros)
   
// Retorna que a operação foi feita com sucesso para a camada do Protheus. 
Return .T.


Exemplo 2 1.B - Testa o web service Agenda criado no exemplo 1.A

Bloco de código
languagecpp
themeEclipse
linenumberstrue
collapsefalse
User Function WSAgenda()
  Local oWsdl
  Local xRet
  Local aOps := {}, aComplex := {}, aSimple := {}
 
  // CRIA O OBJETO DA CLASSE TWSDLMANAGER
  oWsdl := TWsdlManager():New()
  
  // SETA O MODO DE TRABALHO DA CLASSE PARA "VERBOSE"
  oWsdl:lVerbose := .T.
 
  // FAZ O PARSE DE UMA URL
  conOut("   realizando parse de url...")
  xRet:= oWsdl:ParseURL( "http://localhost:8079/ws/Agenda.apw?WSDL" )
  if xRet== .F.
    conOut("   realizando parse de url... erro: " + oWsdl:cError)
    Return
  else 
    conOut("   realizando parse de url... feito")
  endif
  conOut(chr(10) + chr(10))

  // LISTA AS OPERACÕES DISPONIVEIS
  conOut("   listando as operacões disponiveis...")
  aOps := oWsdl:ListOperations()
  if Len( aOps ) == 0
    conOut("   listando as operacões disponiveis... erro: " + oWsdl:cError)
    Return
  else
    varinfo( "aOps", aOps )
    conOut("   listando as operacões disponiveis... feito")
  endif
  conOut(chr(10) + chr(10))


  // DEFINE UMA OPERACAO
  conOut("  setando operacao LISTACONTATOS...")
  xRet:= oWsdl:SetOperation( "LISTACONTATOS" )
   if xRet== .F.
     conOut("  setando operacao LISTACONTATOS... erro: " + oWsdl:cError)
     Return
  else
    conOut("  setando operacao LISTACONTATOS... feito")
  endif
  conOut(chr(10) + chr(10))


  // LISTA OS ELEMENTOS COMPLEXOS DA OPERACAO
  conOut("   listando elementos complexos da operacao...")
  aComplex := oWsdl:NextComplex()
  varinfo( "aComplex", aComplex )
  conOut("   listando elementos complexos da operacao... feito")
  conOut(chr(10) + chr(10))


  // LISTA OS ELEMENTOS SIMPLES DA OPERACAO
  conOut("   listando elementos simples da operacao...")
  aSimple := oWsdl:SimpleInput()
  varinfo( "aSimple", aSimple )
  conOut("   listando elementos simples da operacao... feito")
  conOut(chr(10) + chr(10))


  // RECEBE E IMPRIME A MENSAGEM FORMATADA PARA ENVIO
  conOut("   pegando mensagem formatada para envio...")
  conout( oWsdl:GetSoapMsg() )
  conOut("   pegando mensagem formatada para envio... feito")
  conOut(chr(10) + chr(10))


  // ENVIA A MENSAGEM PARA O SERVIDOR
  conOut("   enviando mensagem para o servidor...")
  xRet:= oWsdl:SendSoapMsg()
  if xRet== .F.
    conOut("   enviando mensagem para o servidor... erro: " + oWsdl:cError )
    Return
  else 
    conOut("   enviando mensagem para o servidor... feito")
  endif
  conOut(chr(10) + chr(10))


  // RECEBE A MENSAGEM DE RESPOSTA
  conOut("   pegando a mensagem de resposta do servidor...")
  conout( oWsdl:GetSoapResponse() )
  conOut("   pegando a mensagem de resposta do servidor... feito")
  conOut(chr(10) + chr(10))


  // DEFINE UMA OPERACAO
  conOut("  setando operacao INSERECONTATOS...")
  xRet:= oWsdl:SetOperation( "INSERECONTATOS" )
  if xRet== .F.
    conOut("  setando operacao INSERECONTATOS... erro: " + oWsdl:cError)
    Return
  else
    conOut("  setando operacao INSERECONTATOS... feito")
  endif
  conOut(chr(10) + chr(10))


  // LISTA OS ELEMENTOS COMPLEXOS DA OPERACAO
  conOut("   listando elementos complexos da operacao...")
  aComplex := oWsdl:NextComplex()
  varinfo( "aComplex", aComplex )
  conOut("   listando elementos complexos da operacao... feito")
  conOut(chr(10) + chr(10))


  // SETA QUANTAS VEZES O ELEMENTO COMPLEXO APARECERÁ
  conOut("   setando ocorrencias de elemento complexo...")
  while ValType( aComplex ) == "A"
    if ( aComplex[2] == "CONTATO" ) .And. ( aComplex[5] == "INSERECONTATOS#1._DADOS#1.REGISTROS#1" )
      occurs := 2 // o objeto complexo aparecerá 2 vezes
    else
      occurs := 0
    endif
    xRet:= oWsdl:SetComplexOccurs( aComplex[1], occurs )
    if xRet== .F.
      conout( "   setando ocorrencias de elemento complexo... erro: erro ao definir elemento " + aComplex[2] + ", ID " + cValToChar( aComplex[1] ) + ", com " + cValToChar( occurs ) + " ocorrencias" )
      return
    endif
    aComplex := oWsdl:NextComplex()
  enddo
  conOut("   setando ocorrencias de elemento complexo... feito")
  conOut(chr(10) + chr(10))

  // LISTA OS ELEMENTOS SIMPLES DA OPERACAO 
  conOut("   listando elementos simples da operacao...")
  aSimple := oWsdl:SimpleInput()
  varinfo( "aSimple", aSimple )
  conOut("   listando elementos simples da operacao... feito")
  conOut(chr(10) + chr(10))

  // SETA OS VALORES DOS ELEMENTOS SIMPLES
  /*  
    cada elemento complexo do nosso exemplo (contato) possui dois elementos simples (nome e telefone);
    No nosso exemplo temos 2 elementos complexos, então temos que setar 4 elementos simples
    setamos cada elemento simples sequencialmente:
      registro 1 propridade 1 do exemplo
      registro 1 propridade 2 do exemplo
      registro 2 propridade 1 do exemplo
      registro 2 propridade 2 do exemplo
  */
  conOut("   localizando posicao do ID e definindo valor da propriedade...")
  nPos := aScan( aSimple, {|aVet| aVet[2] == "NOME" .AND. aVet[5] == "INSERECONTATOS#1._DADOS#1.REGISTROS#1.CONTATO#1" })
  conOut("      ID: " + cValToChar(nPos) + " | PROPRIEDADE: " + cValToChar(aSimple[nPos][2]))
  xRet := oWsdl:SetValue( aSimple[nPos][1], "Ciclano" )
  nPos := aScan( aSimple, {|aVet| aVet[2] == "TELEFONE" .AND. aVet[5] == "INSERECONTATOS#1._DADOS#1.REGISTROS#1.CONTATO#1" })
  conOut("      ID: " + cValToChar(nPos) + " | PROPRIEDADE: " + cValToChar(aSimple[nPos][2]))
  xRet := oWsdl:SetValue( aSimple[nPos][1], "98765" )
  nPos := aScan( aSimple, {|aVet| aVet[2] == "NOME" .AND. aVet[5] == "INSERECONTATOS#1._DADOS#1.REGISTROS#1.CONTATO#2" })
  conOut("      ID: " + cValToChar(nPos) + " | PROPRIEDADE: " + cValToChar(aSimple[nPos][2]))
  xRet := oWsdl:SetValue( aSimple[nPos][1], "Beltrano" )
  nPos := aScan( aSimple, {|aVet| aVet[2] == "TELEFONE" .AND. aVet[5] == "INSERECONTATOS#1._DADOS#1.REGISTROS#1.CONTATO#2" })
  conOut("      ID: " + cValToChar(nPos) + " | PROPRIEDADE: " + cValToChar(aSimple[nPos][2]))
  xRet := oWsdl:SetValue( aSimple[nPos][1], "912345" )
  conOut("   localizando posicao do ID e definindo valor da propriedade... feito")
  conOut(chr(10) + chr(10))

  // EXIBE A MENSAGEM QUE SERÁ ENVIADA
  conOut("   pegando mensagem formatada para envio...")
  conout( oWsdl:GetSoapMsg() )
  conOut("   pegando mensagem formatada para envio... feito")
  conOut(chr(10) + chr(10))


  // ENVIA A MENSAGEM SOAP AO SERVIDOR
  conOut("   enviando mensagem para o servidor...")
  xRet:= oWsdl:SendSoapMsg()
  if xRet== .F.
    conout(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
    conOut("   enviando mensagem para o servidor... erro: " + oWsdl:cError )
    Return
  else 
    conOut("   enviando mensagem para o servidor... feito")
  endif
  conOut(chr(10) + chr(10))


  // PEGA A MENSAGEM DE RESPOSTA
  conOut("   pegando a mensagem de resposta do servidor...")
  conout( oWsdl:GetSoapResponse() )
  conOut("   pegando a mensagem de resposta do servidor... feito")
  conOut(chr(10) + chr(10))

Return


Exemplo 3 2 - Testa um web service externo com elementos simples

Bloco de código
languagecpp
themeEclipse
linenumberstrue
collapsefalse
User Function Teste()
  Local oWsdl
  Local xRet
  Local aOps := {}, aComplex := {}, aSimple := {}

  // Cria o objeto da classe TWsdlManager
  oWsdl := TWsdlManager():New()

  // Faz o parse de uma URL
  xRet := oWsdl:ParseURL( "http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL" )
  if xRet == .F.
    conout( "Erro: " + oWsdl:cError )
    Return
  endif

  aOps := oWsdl:ListOperations()

  if Len( aOps ) == 0
    conout( "Erro: " + oWsdl:cError )
    Return
  endif

  varinfo( "", aOps )

  // Define a operação
  xRet := oWsdl:SetOperation( "GetCityForecastByZIP" )
  //xRet := oWsdl:SetOperation( aOps[1][1] )
  if xRet == .F.
     conout( "Erro: " + oWsdl:cError )
     Return
  endif

  aComplex := oWsdl:NextComplex()
  varinfo( "", aComplex )

  aSimple := oWsdl:SimpleInput()
  varinfo( "", aSimple )

  // Define o valor de cada parâmeto necessário
  xRet := oWsdl:SetValue( 0, "90210" )
  //xRet := oWsdl:SetValue( aSimple[1][1], "90210" )
  if xRet == .F.
    conout( "Erro: " + oWsdl:cError )
    Return
  endif

  // Exibe a mensagem que será enviada
  conout( oWsdl:GetSoapMsg() )

  // Envia a mensagem SOAP ao servidor
  xRet := oWsdl:SendSoapMsg()
  if xRet == .F.
    conout( "Erro: " + oWsdl:cError )
    Return
  endif

  // Pega a mensagem de resposta
  conout( oWsdl:GetSoapResponse() )

  if xRet == .F.
    conout( "Erro: " + oWsdl:cError )
    Return
  endif
Return


Exemplo 4 3 - Testa um web service externo com elementos complexos

...