Try OpenEdge Now
skip to main content
Web Services
Creating ABL Clients to Consume OpenEdge SOAP Web Services : Handling Errors in ABL Requests to OpenEdge SOAP Web Services : Examples of ABL accessing a SOAP fault : Structured error handling example
 
Structured error handling example
The code in the following example:
1. Encloses the logic in a simple block to demonstrate the placement and syntax of the CATCH block. In this simple example, if an error other than a system error occurred in the block, the error would be thrown to the enclosing block, which is the main block of the procedure (.p) file.
2. Handles any Progress.Lang.SoapFaultError error object generated by the AVM with the first CATCH block. This class is essentially a wrapper for the built-in SOAP-fault object.
3. Assigns a handle variable (hSoapFault) to the SOAP-fault object returned by the AVM for code readability.
4. Examines the values of SOAP fault elements, as required, using appropriate attributes (SOAP-FAULT-CODE) on the SOAP-fault object handle.
5. Uses the ABL VALID-HANDLE function to determine if this SOAP fault has SOAP fault detail by testing the validity of the handle returned by hSoapFault:SOAP-FAULT-DETAIL.
6. Assigns a handle variable (hSoapFaultDetail) to the SOAP fault-detail object returned by the hSoapFault:SOAP-FAULT-DETAIL attribute for code readability.
7. Returns the root node of the underlying SOAP fault <detail> element by using the hSoapFaultDetail:GET-NODE( ) method to assign the root node to the x-noderef object referenced by the handle variable hxnoderef.
8. Use the methods and attributes of the X-noderef object handle (hxnoderef) and additional handle variables to walk the XML DOM subtree referenced by hxnoderef to examine the content of the SOAP fault <detail> element as specified by the WSDL for the Web service.
9. Delete or throw the error object in the application code once it is handled by a CATCH block. Unhandled error objects are deleted automatically by the AVM.
10. Handles any system error (other than SoapFaultError) raised in the ON ERROR block with the second CATCH block. Because SoapFaultError is a subtype of SysError, the CATCH block handling SoapFaultError must occur before the more general CATCH block for all SysError objects.
11. Executes the FINALLY block whether the second CATCH block succeeded or failed. This makes the FINALLY block a good place to put clean up code.

Sample SOAP fault procedure

DEFINE VARIABLE hWS AS HANDLE.
DEFINE VARIABLE hStockPortType AS HANDLE.
DEFINE VARIABLE price AS DECIMAL.

/*1*/
DO ON ERROR UNDO, THROW:

  CREATE SERVER hWS.

  /* Create a WebServicePortType object, using server & port information. */
  hWS:CONNECT( "-WSDL http: //www.stockvend.com/application/wsdl/stock.wsdl
                -Service stockSVC
                -Port stockPort" ).

  RUN stock SET hStockPortType ON SERVER hWS.

  RUN getPrice IN hStockPortType( INPUT "error", OUTPUT price ).

/*2*/
  /* This CATCH handles SoapFaultErrors and ignores all other system errors.*/
  CATCH mySoapErrorObject AS Progress.Lang.SoapFaultError:

/*3*/
    DEFINE VARIABLE hSoapFault AS HANDLE.
    hSoapFault = mySoapErrorObject:SoapFault.

/*4*/
    IF INDEX("VersionMismatch", hSoapFault:SOAP-FAULT-CODE) > 0 THEN DO:

/*5*/
      IF VALID-HANDLE( hSoapFault:SOAP-FAULT-DETAIL ) THEN DO:

/*6*/
        DEFINE VARIABLE hSoapFaultDetail as HANDLE.
        ASSIGN hSoapFaultDetail = hSoapFault:SOAP-FAULT-DETAIL.

        DEFINE VARIABLE hxnoderef AS HANDLE.
        CREATE X-NODEREF hxnoderef.

/*7*/
        hSoapFaultDetail:GET-NODE( hxnoderef ).

/*8*/
        /* From here the application can walk the detail XML and retrieve the
           relevant information. */

/*9*/
        DELETE OBJECT mySoapErrorObject.
      END. /* Return SOAP-FAULT-CODE info */
    END. /* Examine SOAP-FAULT-DETAIL */
  END CATCH.

/*10*/
  CATCH mySystemErrorObject AS Progress.Lang.SysError:
    /* Handle any other system error. Since SysError is a superclass of
       SoapFaultError, this CATCH would also handle SoapFaultError if the
       more specific CATCH block did not come first. */
    DELETE OBJECT mySysErrorObject.
  END CATCH.

/*11*/
  FINALLY:
    DELETE PROCEDURE hStockPortType.
    hWS:DISCONNECT( ).
  END FINALLY.

END /* DO ON ERROR */