Connectivity to Web Services issue

b-707

Member
Hi All,

We built system that works against some Web Service.
Generally everything works nice, but there is an issue.

If an endpoint is set wrong in our configuration, the first time we try to connect to a server
it throws back, with messages of connectivity issue.

If we try it again, once it comes to

hWebService:CONNECT(wsdlPath)

progress just stops, and it takes ages to come back.

Does anybody have an idea what happens?


CLASS CBWSConnector:

DEF VAR hServiceSoap AS HANDLE NO-UNDO.
DEF VAR hWebService AS HANDLE NO-UNDO.


CONSTRUCTOR PUBLIC CBWSConnector (INPUT portName AS CHARACTER, INPUT wsdlAddress AS CHARACTER):

DEF VAR wsdlPath AS CHAR INIT "-WSDL" NO-UNDO.

ASSIGN wsdlPath = wsdlPath + " " + wsdlAddress.

CREATE SERVER hWebService.

hWebService:CONNECT(wsdlPath).

RUN VALUE(portName) SET hServiceSoap ON hWebService.


END CONSTRUCTOR.

METHOD PUBLIC VOID DisconnectWS().

hWebService:DISCONNECT() NO-ERROR.
DELETE OBJECT hWebService NO-ERROR.

END METHOD.

........MORE METHODS.................


END CLASS.

I use the Disconnect method to explicitly disconnect the server upon completion.

METHOD PUBLIC CHARACTER AuthenticateUser(uname AS CHARACTER, password AS CHARACTER).
DEFINE VARIABLE auth AS CHARACTER NO-UNDO.
DEFINE VARIABLE Conn AS CBWSConnector NO-UNDO.

Conn = New CBWSConnector(CBWSConnector:userServicePortName, userManagementServiceWSDLLink).

ASSIGN
auth = Conn:AuthenticateUser_WS(uname,password).

Conn:DisconnectWS() NO-ERROR.

DELETE OBJECT Conn NO-ERROR.

RETURN auth.
END METHOD.

Thank You!
 

b-707

Member
What is the exact error message you get?

Heavy Regards, RealHeavyDude.

The first attempt, when I use the wrong endpoint it returns this:

Error loading WSDL document http://*****/ManagementService.asmx?wsdl line 1 column 6: error: The parsed node is not a wsdl:definitions document! (11748)
SERVER is not connected. (5451)
Invalid or inappropriate server handle specified for RUN UserManagementServiceSoap ... ON SERVER statement. (5453)
Could not evaluate procedure handle expression while trying to execute AuthenticateUser.

The second time it just dies trying to
hWebService:CONNECT(wsdlPath).

Doesn't show error. Just dies.
 

RealHeavyDude

Well-Known Member
The first error message you get - the 11748 - says it all. Progress says that the WSDL does not conform to the WS-I recommendation and obviously they are particular about it.
Don't know whether this help, but that's what the KB says. There are other results if you browse the KB, but I think this one is relevant to you:
Code:
 http://knowledgebase.progress.com/articles/Article/P111028?retURL=%2Fapex%2FProgressKBHome&popup=false

Heavy Regards, RealHeavyDude.
 

b-707

Member
The first error message you get - the 11748 - says it all. Progress says that the WSDL does not conform to the WS-I recommendation and obviously they are particular about it.
Don't know whether this help, but that's what the KB says. There are other results if you browse the KB, but I think this one is relevant to you:
Code:
 http://knowledgebase.progress.com/articles/Article/P111028?retURL=%2Fapex%2FProgressKBHome&popup=false

Heavy Regards, RealHeavyDude.
This message makes sense - the endpoint set wrong. There is no wsdl where I pointing the request to. This is done just to mimic situation when webservice doesn't respond of whatever reason. Again - my issue - why when I try to create server and connect it the second time it goes out and never returns?
 

RealHeavyDude

Well-Known Member
What do you mean by try again?

Anyway, in your code excerpts ( please use CODE tags next time - makes the code much better readable ) I don't see any error handling that makes sure that you don't produce a memory leak - meaning code that ensures that the server object you've created gets deleted properly and does not remain in memory until you close the session.

I don't know how the connection pool for state-free connections ( in your case to a web service ) is handled internally by the ABL when you have other server objects hanging about in the session. Probably it is an explanation for the erratic behavior you see.

Heavy Regards, RealHeavyDude.
 

b-707

Member
What do you mean by try again?

Anyway, in your code excerpts ( please use CODE tags next time - makes the code much better readable ) I don't see any error handling that makes sure that you don't produce a memory leak - meaning code that ensures that the server object you've created gets deleted properly and does not remain in memory until you close the session.

I don't know how the connection pool for state-free connections ( in your case to a web service ) is handled internally by the ABL when you have other server objects hanging about in the session. Probably it is an explanation for the erratic behavior you see.

Heavy Regards, RealHeavyDude.

I see... thanks... I'll probably remove NO-ERROR to see what happens.
 

b-707

Member
Just checked it - removed all of the NO-ERROR on disconnection and object deletion. Nothing happens. No errors thrown.
 

jonb

New Member
It would be helpful if you isolate the code into a runnable sample. I just tried this:

Code:
DEFINE VARIABLE hServer AS HANDLE NO-UNDO.


DO ON ERROR UNDO, LEAVE:
   CREATE SERVER hServer.
   hServer:CONNECT("-H www.google.com -P 80 -WSDL http://www.google.com/").
END.


hServer:DISCONNECT() NO-ERROR.
DELETE OBJECT hServer NO-ERROR.


DO ON ERROR UNDO, LEAVE:
   CREATE SERVER hServer.
   hServer:CONNECT("-H www.google.com -P 80 -WSDL http://www.google.com/").
END.

I got the expected error message both times with no delay. Commenting out the disconnect and delete I still got the error both times with no delay. So it could be something else in your code causing the delay. Or could it be the web server you're connecting to causing the delay?
 

timk519

New Member
I had a similar issue, and had to go to Progress Tech Support to get all the issues and configurations resolved in order to get WebServices working.
 

Stefan

Well-Known Member
Just checked it - removed all of the NO-ERROR on disconnection and object deletion. Nothing happens. No errors thrown.

OpenEdge version?
Does your client also crash silently if you connect from a procedure instead of using a class?

If I attempt to connect to a bogus wsdl with OE11.1 32-bit on Vista x64, it just keeps erroring out with 11748 as expected:

Code:
DEF VAR hwebservice  AS HANDLE   NO-UNDO.
DEF VAR hservicesoap AS HANDLE   NO-UNDO.
DEF VAR ii           AS INTEGER  NO-UNDO.


DO ii = 1 TO 5:
   DO ON ERROR UNDO, LEAVE:
      CREATE SERVER hWebService.
      IF hWebService:CONNECT("-WSDL http://progresstalk.com") THEN
         MESSAGE "connected" VIEW-AS ALERT-BOX.
   END.


   DELETE OBJECT hwebservice.
END.


MESSAGE "done" VIEW-AS ALERT-BOX.
 

RealHeavyDude

Well-Known Member
Just removing the NO-ERROR option on an ABL statement does not mean that you handle errors!

Especially when you deal with handle-based dynamic objects that you create at run time you need to make sure that they are managed properly by your code. The ABL won't do that for you for handle-based dynamic objects - it only does so for static objects that are resolved at compile time. Full Stop.

If I were you I would have a look in the structured error handling that was introduced with OpenEdge 10 ( or was it with OE10.1B ? ). Look for the CATCH key word in the online help.
Heavy Regards, RealHeavyDude.
 

b-707

Member
Just removing the NO-ERROR option on an ABL statement does not mean that you handle errors!

Especially when you deal with handle-based dynamic objects that you create at run time you need to make sure that they are managed properly by your code. The ABL won't do that for you for handle-based dynamic objects - it only does so for static objects that are resolved at compile time. Full Stop.

If I were you I would have a look in the structured error handling that was introduced with OpenEdge 10 ( or was it with OE10.1B ? ). Look for the CATCH key word in the online help.
Heavy Regards, RealHeavyDude.

This is getting even more interesting. I applied the CATCH structure in the constructor:

Code:
CONSTRUCTOR PUBLIC CBWSConnector (INPUT portName AS CHARACTER, INPUT wsdlAddress AS CHARACTER):
    
            DEF VAR wsdlPath AS CHAR INIT "-WSDL" NO-UNDO.
            
            ASSIGN wsdlPath = wsdlPath + " " + wsdlAddress.
            
            MESSAGE "START CREATION OF SERVER".
            CREATE SERVER hWebService.
            MESSAGE "END CREATION OF SERVER".
            
            DO ON ERROR UNDO, LEAVE: 
                MESSAGE "START CONNECTION TO SERVER".
                hWebService:CONNECT(wsdlPath).        
                MESSAGE "END CONNECTION TO SERVER".
                
                MESSAGE "START RUNNING ON " portName.
                RUN VALUE(portName) SET hServiceSoap ON hWebService.            
                MESSAGE "END RUNNING ON " portName.
                
                CATCH oneError AS Progress.Lang.SysError: 
                    MESSAGE "CONNECTION ERROR: " oneError:GetMessage(1). 
                    DELETE OBJECT hWebService.                        
                END CATCH.                 
            END.               
        
    END CONSTRUCTOR.

This changed nothing BUT......
If I set just the wrong URL at the level of the root folder, this throws "Cannot resolve URL" and continue working as expected. No problem.

But if the URL is wrong just in the name of the wsdl file, my problem comes back. First time nicely throws exceptions and returns control, but the second time if I hit the same endpoint again it goes and never comes back.

And again, it dies on
hWebService:CONNECT(wsdlPath).
 

RealHeavyDude

Well-Known Member
Still I don't see any code that handles the dynamic server object that you create. You should include a FINALLY block after the CATCH block that makes sure that the dynamic server object gets removed in any case. Plus, personally, I would never try a connection to any server in the constructor of a class. If it fails you are not able to instantiate the object gracefully. I would put the logic in a method instead that I would call immediately after the object has been instantiated. Just my 2 cents.

This is some piece of code that you should include after the CATCH block in any case ( coded in Firefox IDE, not syntax checked ... ):
Code:
FINALLY: IF VALID-HANDLE ( hWebService ) THEN DELETE OBJECT hWebService. END FINALLY.
Heavy Regards, RealHeavyDude.
 

b-707

Member
Still I don't see any code that handles the dynamic server object that you create. You should include a FINALLY block after the CATCH block that makes sure that the dynamic server object gets removed in any case. Plus, personally, I would never try a connection to any server in the constructor of a class. If it fails you are not able to instantiate the object gracefully. I would put the logic in a method instead that I would call immediately after the object has been instantiated. Just my 2 cents.

This is some piece of code that you should include after the CATCH block in any case ( coded in Firefox IDE, not syntax checked ... ):
Code:
FINALLY: IF VALID-HANDLE ( hWebService ) THEN DELETE OBJECT hWebService. END FINALLY.
Heavy Regards, RealHeavyDude.

RealHeavy - this is a constructor, why would I destroy it if the connection is OK?
 

b-707

Member
OpenEdge version?
Does your client also crash silently if you connect from a procedure instead of using a class?

If I attempt to connect to a bogus wsdl with OE11.1 32-bit on Vista x64, it just keeps erroring out with 11748 as expected:

Code:
DEF VAR hwebservice  AS HANDLE   NO-UNDO.
DEF VAR hservicesoap AS HANDLE   NO-UNDO.
DEF VAR ii           AS INTEGER  NO-UNDO.


DO ii = 1 TO 5:
   DO ON ERROR UNDO, LEAVE:
      CREATE SERVER hWebService.
      IF hWebService:CONNECT("-WSDL http://progresstalk.com") THEN
         MESSAGE "connected" VIEW-AS ALERT-BOX.
   END.


   DELETE OBJECT hwebservice.
END.


MESSAGE "done" VIEW-AS ALERT-BOX.

Stefan, 10.2B

First of - you should close the connection of hwebservice before you delete it.

To you question - it doesn't matter where I am hitting webservice from. I used your procedural style code and got the same result - first time exception, the second time it dies somewhere and doesn't return.

I'll bring more details:

Let's assume this is the correct URI:
Code:
http://wpgch/CBox47/Services/UserManagementService.asmx?wsdl
If I cause the failure by using
Code:
http://wpgch/CBox47[COLOR=#ff0000]XXXXXX[/COLOR]/Services/UserManagementService.asmx?wsdl
- this returns "can not resolve", and continue workin normally.

If I fake the wsdl name like this:
Code:
http://wpgch/CBox47/Services/UserManagementService[COLOR=#ff0000]XXX[/COLOR].asmx?wsdl
- first time it'll throw wsdl error exception, the second time it'll die.
 

b-707

Member
This is not a delay, this is just death. The CONNECT never returns any responce and the process is hanging
 

Stefan

Well-Known Member
Stefan, 10.2B
No service pack?!? Which OS?

First of - you should close the connection of hwebservice before you delete it.
Only if the connection is successful.

To you question - it doesn't matter where I am hitting webservice from. I used your procedural style code and got the same result - first time exception, the second time it dies somewhere and doesn't return.

I'll bring more details:

Let's assume this is the correct URI:
Code:
http://wpgch/CBox47/Services/UserManagementService.asmx?wsdl
If I cause the failure by using
Code:
http://wpgch/CBox47[COLOR=#ff0000]XXXXXX[/COLOR]/Services/UserManagementService.asmx?wsdl
- this returns "can not resolve", and continue workin normally.

If I fake the wsdl name like this:
Code:
http://wpgch/CBox47/Services/UserManagementService[COLOR=#ff0000]XXX[/COLOR].asmx?wsdl
- first time it'll throw wsdl error exception, the second time it'll die.

What is the web server returning if you enter that URL twice in a browser?

Just found an open user ManagementService.asmx via google (nimbushd) - it connects fine with correct url and errors fine continuously with an XXX added before the asmx (using 10.2B04 32-bit on Win7 x64):

Code:
Error loading WSDL document  http://api.nimbushd.com/Users/UserManagementServiceXXX.asmx?WSDL : Cannot resolve URI: 'http://api.nimbushd.com/Users/UserManagementServiceXXX.asmx?WSDL' status code: 404 (11748)
 

b-707

Member
Stefan, I am out of the office - it's friggen Friday night :) Don't know what the SP. It runs on Solaris. Webservice itself is OK. The one you found is not the same. I hit the webservice of Checkbox, here, internally. There is nothing to do with the google's one.

If I hit it of browser twice, it works OK. If I reproduce the same situation from DotNet, it works excellent. Just calls from Progress kill my mental health :)
 
Top