Rodrigo entrou em uma roubada. Perguntou-me: "..иαldσ estou com problemas para gerar um client de um WebService no Protheus, não sei se é minha instalação. Será que você poderia me ajudar?" (foi + ou - assim ... rs)
manda-o-link-aew (respondi eu). e;
taí: http://201.48.221.162:2000/ServiceFuturePMS/service?WSDL
Testei.... hummmmm.... Olha a mensagem emitida pelo IDE:
Estabelecendo conexão com o server...
Por favor aguarde. Obtendo descrição do WebService...
Erro na obtenção da descrição do WebService:
Invalid function return for WSDLSource Call.
Finalizando conexão com o server...
Ok
|
Bem... não me ajudou muito.... Opa.... "Invalid function return for WSDLSource Call".... hummmmmm.... WSDLSource... acho que é esse carinha aqui quem tenta gerar o client.... Vamos executá-lo diretamente.... Sintaxe: WSDLSource( cUrl ) : [lSucess][cSource/cError].
WSDLSource( "http://201.48.221.162:2000/ServiceFuturePMS/service?WSDL" )
NIL
|
Retorno NIL, estava eperando um Array.... Vamos ver o Console do server...
[FATAL][SERVER] [Thread 1356] [THROW] String size overflow! at file c:\advtec9_101202a\lib_base\stringz.hpp line 355
|
String size overflow! (Oops: Erro, erro no servidor, Bad, bad server ).....
Rodrigo, seguinte, o protheus "p...". A restrição no tamanho da string imposta pelo pessoal de Tecnologia do Protheus não vai deixar que gere o seu Client.
Tem alguma solução? (perguntou ele).... e a resposta foi: 3 Possíveis soluções.
1 ) Abrir um chamado da Totvs/Microsiga e solicitar que ampliem o limite da string;
2 ) Entrar em contato com o Desenvolvedor do WebService e pedir para que ele divida o WS em Vários outros WS ; e
3 ) Usar uma aplicação externa para resolver o WS e retornar a informação ao Protheus. Testei no Windows® PowerShell® e funciona que é uma beleza.
O que acha?
"O pessoal aqui não acredita que essa ultima solução funcione. Tem como mandar um exemplo simples? Tem o Método CountUsers que retorna o número de usuários."....
heheheheh.... demorô.....
Segue o Código:
#INCLUDE "APWEBSRV.CH"
#INCLUDE "PROTHEUS.CH"
#INCLUDE "TRYEXCEPTION.CH"
/*/
WSSERVICE: u_FuturePMS
Autor: Marinaldo de Jesus
Data: 05/05/2011
Descricao: Usar PowerShell para Resolver WS nao suportado pelo Protheus em Funcao de Limitacao da Linguagem
/*/
WSSERVICE u_FuturePMS DESCRIPTION "Integracao Protheus x PowerShell x FuturePMS" NAMESPACE "http://localhost/u_futurepms.apw"
WSDATA CountUser AS INTEGER
WSDATA PSException AS BOOLEAN
WSMETHOD CountUsers DESCRIPTION "Retornar o Numero de Usuarios do ServiceFuturePMS"
ENDWSSERVICE
/*/
WSMETHOD: CountUsers
Autor: Marinaldo de Jesus
Data: 05/05/2011
Descricao: Encapsular a Chamada ao Metodo CountUsers do WS ServiceFuturePMS executando-o atraves do PS e retornando o Resultado
/*/
WSMETHOD CountUsers WSRECEIVE PSException WSSEND CountUser WSSERVICE u_FuturePMS
Local aFileErase := {}
Local cCRLF := CRLF
Local cPsHome := ""
Local cPsScript := ""
Local cRootPath := ""
Local cPSFileSript := ""
Local cPathFileXml := ""
Local cFullPathXml := ""
Local cFullPathPS1 := ""
Local cWsResultPath := "\PPSIntWs\"
Local cWSFileResult := ""
Local cXmlError := ""
Local cXmlWarning := ""
Local lWsMethodRet := .T.
Local oXml
Local oException
TRYEXCEPTION
cRootPath := GetSrvProfString( "RootPath" , "" )
IF ( SubStr( cRootPath , -1 ) == "\" )
cRootPath := SubStr( cRootPath , 1 , Len( cRootPath ) - 1 )
EndIF
IF !lIsDir( cWsResultPath )
MakeDir( cWsResultPath )
IF !lIsDir( cWsResultPath )
ExUserException( "Impossível Criar o Diretório: " + cWsResultPath )
EndIF
EndIF
cWSFileResult := CriaTrab( NIL , .F. )
cPathFileXml := ( cWsResultPath + cWSFileResult )
While ( File( cPathFileXml + ".xml" ) .or. File( cPathFileXml + ".ps1" ) )
cWSFileResult := CriaTrab( NIL , .F. )
cPathFileXml := ( cWsResultPath + cWSFileResult )
End While
cPSFileSript := ( cWSFileResult + ".ps1" )
cPathFileXml += ".xml"
aAdd( aFileErase , cPathFileXml )
cFullPathXml := ( cRootPath + cPathFileXml )
cPSFileSript := ( cWsResultPath + cPSFileSript )
cFullPathPS1 := ( cRootPath + cPSFileSript )
aAdd( aFileErase , cPSFileSript )
DEFAULT Self:PSException := .F.
DEFAULT PSException := Self:PSException
/*/
Para que o "script" possa ser executado faz-se necessario autoriza-lo atraves do Windows PowerShell, sendo
assim, execute o Windows PowerShell e digite o seguinte comando:
get-help about_signing.
Esse comando ira listar as opcoes de "Diretivas de Assinatura e de Execucao" de "Script". Leia-as atentamente.
Mas se quiser pular esse passo (eu nao recomendo) digite o seguinte comando abaixo no Windows PowerShell:
Set-ExecutionPolicy Unrestricted.
Esse comando fara que qualquer "Script" seja executado em sua máquina (mas atente para os itens de seguranca
listados aa partir do comando get-help about_signing).
/*/
cPsScript := " [int]$CountUserResult = 0"
cPsScript += cCRLF
cPsScript += " [boolean]$CountUserResultSpecified = $True"
cPsScript += cCRLF
cPsScript += " $ws = New-WebServiceProxy -URI http://201.48.221.162:2000/ServiceFuturePMS/service?WSDL"
cPsScript += cCRLF
cPsScript += " $ws.CountUsers( [ref]$CountUserResult , [ref]$CountUserResultSpecified )"
cPsScript += cCRLF
cPsScript += " [string]$PSOutFile = '" + cFullPathXml + "'"
cPsScript += cCRLF
cPsScript += " $xml = " + '"' + "$CountUserResult" + '"'
cPsScript += cCRLF
cPsScript += " $xml | Out-File $PSOutFile"
cPsScript += cCRLF
IF ( PSException )
cPsScript := AddPsException( @cPsScript , @cCRLF )
EndIF
MemoWrite( cPSFileSript , cPsScript )
cPsHome := AllTrim( GetSrvProfString( "PSHome" , "C:\WINDOWS\system32\WindowsPowerShell\v1.0\" ) )
IF !( SubStr( cPsHome , -1 ) == "\" )
cPsHome += "\"
EndIF
IF !( WaitRunSrv( cPsHome + "powershell.exe " + cFullPathPS1 , .T. , cPsHome ) )
ExUserException( "Impossivel Executar o PowerShell" )
EndIF
IF !File( cPathFileXml )
ExUserException( "XML não carregado: " + cPathFileXml )
EndIF
oXml := XmlParserFile( @cPathFileXml , "_" , @cXmlError , @cXmlWarning )
IF !( ValType( oXml ) == "O" )
IF !Empty( cXmlError )
ExUserException( cXmlError )
EndIF
ExUserException( "Impossovel Carregar o XML: " + cPathFileXml )
EndIF
Self:CountUser := Val( oXml:_Result:_CountUser:Text )
CountUser := Self:CountUser
CATCHEXCEPTION USING oException
lWsMethodRet := .F.
SetSoapFault( ProcName() , CaptureError() )
ENDEXCEPTION
aEval( aFileErase , { |cFile| IF( File( cFile ) , fErase( cFile ) , NIL ) } )
Return( lWsMethodRet )
/*/
WSMETHOD: AddPsException
Autor: Marinaldo de Jesus
Data: 05/05/2011
Descricao: Adicionar Tratamento de Excecao no Script em PowerShell
/*/
Static Function AddPsException( cPsScript , cCRLF )
Local cPSException := ""
Local cMsgException := " 'Não foi possível conectar-se a http://201.48.221.162:2000/ServiceFuturePMS/service?WSDL'"
cPSException := "try"
cPSException += cCRLF
cPSException += "{"
cPSException += cCRLF
cPSException += cPsScript
cPSException += cCRLF
cPSException += "}"
cPSException += cCRLF
cPSException += "catch"
cPSException += cCRLF
cPSException += "{"
cPSException += cCRLF
cPSException += cMsgException
cPSException += cCRLF
cPSException += "}"
cPSException += cCRLF
Return( cPSException )
|
e o Client gerado a partir dele:
#INCLUDE "PROTHEUS.CH"
#INCLUDE "APWEBSRV.CH"
/* ===============================================================================
WSDL Location http://200.143.193.75:8081/ws/U_FUTUREPMS.apw?WSDL
Gerado em 05/05/11 09:58:21
Observações Código-Fonte gerado por ADVPL WSDL Client 1.101007
Alterações neste arquivo podem causar funcionamento incorreto
e serão perdidas caso o código-fonte seja gerado novamente.
=============================================================================== */
User Function _WHYOFUC ; Return // "dummy" function - Internal Use
/* -------------------------------------------------------------------------------
WSDL Service WSU_FUTUREPMS
------------------------------------------------------------------------------- */
WSCLIENT WSU_FUTUREPMS
WSMETHOD NEW
WSMETHOD INIT
WSMETHOD RESET
WSMETHOD CLONE
WSMETHOD COUNTUSERS
WSDATA _URL AS String
WSDATA _HEADOUT AS Array of String
WSDATA lPSEXCEPTION AS boolean
WSDATA nCOUNTUSERSRESULT AS integer
ENDWSCLIENT
WSMETHOD NEW WSCLIENT WSU_FUTUREPMS
::Init()
If !FindFunction("XMLCHILDEX")
UserException("O Código-Fonte Client atual requer os executáveis do Protheus Build [7.00.101202A-20110330] ou superior. Atualize o Protheus ou gere o Código-Fonte novamente utilizando o Build atual.")
EndIf
Return Self
WSMETHOD INIT WSCLIENT WSU_FUTUREPMS
Return
WSMETHOD RESET WSCLIENT WSU_FUTUREPMS
::lPSEXCEPTION := NIL
::nCOUNTUSERSRESULT := NIL
::Init()
Return
WSMETHOD CLONE WSCLIENT WSU_FUTUREPMS
Local oClone := WSU_FUTUREPMS():New()
oClone:_URL := ::_URL
oClone:lPSEXCEPTION := ::lPSEXCEPTION
oClone:nCOUNTUSERSRESULT := ::nCOUNTUSERSRESULT
Return oClone
// WSDL Method COUNTUSERS of Service WSU_FUTUREPMS
WSMETHOD COUNTUSERS WSSEND lPSEXCEPTION WSRECEIVE nCOUNTUSERSRESULT WSCLIENT WSU_FUTUREPMS
Local cSoap := "" , oXmlRet
BEGIN WSMETHOD
cSoap += ''
cSoap += WSSoapValue("PSEXCEPTION", ::lPSEXCEPTION, lPSEXCEPTION , "boolean", .T. , .F., 0 , NIL, .T.)
cSoap += ""
oXmlRet := SvcSoapCall( Self,cSoap,;
"http://localhost/u_futurepms.apw/COUNTUSERS",;
"DOCUMENT","http://localhost/u_futurepms.apw",,"1.031217",;
"http://200.143.193.75:8081/ws/U_FUTUREPMS.apw")
::Init()
::nCOUNTUSERSRESULT := WSAdvValue( oXmlRet,"_COUNTUSERSRESPONSE:_COUNTUSERSRESULT:TEXT","integer",NIL,NIL,NIL,NIL,NIL,NIL)
END WSMETHOD
oXmlRet := NIL
Return .T.
|
Compile o WSServer, gere o Client baseado na sua URL, teste e me diga se funciona ou não.... Foi um exemplo bem simples. Poderia ter retornado o xml diretamente, mas nesse caso não faria sentido.
Eu testei aqui, e olha o resultado.
NameSpace http://localhost/u_futurepms.apw
URL Location http://200.143.193.75:8081/ws/
Nome do Serviço U_FUTUREPMS
Método do Serviço COUNTUSERS
Resposta da Requisição SOAP
1
|
Bendita WaitRunSrv() e salve o Windows® PowerShell® (a Totvs bem podia contratar o Engenheiro que planejou o novo Shell do Windows® para reescrever a tecnologia Protheus/by you... o que acham ... rs)
Considerações:
1 ) O Pessoal da Tecnologia Protheus deveria rever essa limitação do tamanho da string no protheus;
2 ) AppServer64 já.
Para baixar os códigos utilizados neste "post", cliquem
aqui.
[]s
иαldσ dj
(simples assim)
Grande Naldo! Mestre no que faz... Para quem pensou que esse nosso desafio nao daria em nada hein!? hehehehe... é como eu ja disse ate para o Bindo... Marinaldo de Jesus é o cara... o resto...bem... o resto é programador... hehehe
ResponderExcluirÉ isso ae Naldo... vc domina e creio q todos que acompanham devia te-lo como exemplo... analizar... modelar.... desenvolver... Se isso fosse de fato feito, talvez o Protheus nao seria uma colcha de retalho! Grande abraço e obrigado pelo desafio!
Naldo, blz?
ResponderExcluirCara... aproveitando seu tópico... to com um problema aqui... será que você poderia me ajudar?
Seguinte... gerei uma função client de webservice no Protheus que foi compilada certinho... desenvolvi uma função para chamar esse client e blz... tudo funcionava ok.
Porém agora mudaram a URL do webservice e tive que alterar minha função client... pra apontar pra essa nova URL... só que agora, na execução do Protheus, retorna a seguinte mensagem:
"The Web application at http://testehh80.empresaX.com.br/formularios could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application."
Só que o endereço do webservice que configurei na função não é esse... segue o código que escrevi abaixo...
oXmlRet := SvcSoapCall( Self,cSoap,;
"http://tempuri.org/GetCadastrosPendentes",;
"DOCUMENT","http://tempuri.org/",,,;
"http://arasrvvirshp002:85/EmpresaXWsSpMicInt/WsSPMicData.asmx")
O mais engraçado é que essa URL ta funcionando legal no browser do IE e o IDE do Protheus também tá gerando a função desse client certinho.
Enfim... não consegui descobrir o motivo pelo qual o Protheus não chama o webservice do endereço que to passando... e devolve essa mensagem de erro apontando pra esse testehh80.empresaX.
Você pode me ajudar nesse problema?
Obrigado e abraços!
Perguntas-Respostas:
Excluir1) Quando regerou o Client utilizou o mesmo arquivo fonte ou gerou um novo? Já que está apenas atualizado deveria manter o mesmo arquivo fonte limpando-o antes de gerar o novo client.
2) Por via das dúvidas (não que isso seja necessário) você excluiu do Projeto e, consequentemente, do RPO o código do Client antigo antes da geração do novo?
Com as informações passadas, as perguntas-respostas acima talvez resolvam o seu "problema". Caso contrário necessitarei de mais informações.
Uma forma de descobrir se, de fato o seu RPO está compilado com a última versão é verificando via "Object Inspector" ou utilizando-se das funções existentes no post:
Protheus :: Advpl :: Usando GetFuncArray, GetApoInfo e VarInfo ( http://goo.gl/k9Fea ).
Se os itens acima elencados não solucionarem o seu problema envie-me o código do client (o novo) e o seu RPO para mail@blacktdn.com.br. Dessa forma poderei comparar ambos os códigos.
TryExeption.ch? Onde consigo essa CH? rsrs
ResponderExcluir