Server / Server stub and handlers |
The COM library enables to intercept high-level web services operation on server side. You can now define three 4GL functions via the following methods of the web service class. They will be executed at different steps of a web service request processing in order to modify the SOAP request, response or the generated WSDL document before or after the SOAP engine has processed it. This helps handle WS-* specifications not supported in the web service API.
FUNCTION CallbackHandler( doc xml.DomDocument ) RETURNING xml.DomDocument
CALL serv.registerWsdlHandler("WSDLHandler")
FUNCTION WSDLHandler(wsdl) DEFINE wsdl Xml.DomDocument DEFINE node Xml.DomNode DEFINE list Xml.DomNodeList DEFINE ind INTEGER DEFINE name STRING # Add a comment LET node = wsdl.createComment( "First modified WSDL via a 4GL callback function") CALL wsdl.prependDocumentNode(node) # Rename input and output parameter in UPPERCASE LET list = wsdl.selectByXPath( "//wsdl:definitions/wsdl:types/xsd:schema/ xsd:complexType/xsd:sequence/xsd:element/xsd:complexType/ xsd:sequence/xsd:element",NULL) -- first input parameter for selectByXPath above -- one string, no spaces! FOR ind=1 TO list.getCount() LET node = list.getItem(ind) LET name = node.getAttribute("name") LET name = name.toUpperCase() CALL node.setAttribute("name",name) END FOR RETURN wsdl END FUNCTION
If NULL is returned from the callback function, an HTTP error will be sent and the ProcessServices() returns error code -20.
CALL serv.registerInputRequestHandler("InputRequestHandler")
FUNCTION InputRequestHandler(in) DEFINE in Xml.DomDocument DEFINE ind INTEGER DEFINE node Xml.DomNode DEFINE copy Xml.DomNode DEFINE tmp Xml.DomNode DEFINE parent Xml.DomNode DEFINE name STRING DEFINE list Xml.DomNodeList # Change input parameter below myrecord in lower case # to follow high-level web service LET list = in.SelectByXPath( "//SOAP:Envelope/SOAP:Body/fjs:EchoDOCRecordRequest/fjs:myrecord/*", "SOAP","http://schemas.xmlsoap.org/soap/envelope/", "fjs","http://www.mycompany.com/webservices") FOR ind = 1 TO list.getCount() LET node = list.getItem(ind) LET parent = node.getParentNode() LET name = node.getLocalName() LET copy = in.createElementNS(node.getPrefix(), name.toLowerCase(),node.getNamespaceURI()) LET tmp = node.getFirstChild() LET tmp = tmp.clone(true) CALL copy.appendChild(tmp) CALL parent.replaceChild(copy,node) END FOR RETURN in END FUNCTION
If NULL is return from the callback function, a SOAP fault will be sent (but can be changed from the output handler) and the ProcessServices() returns error code -18.
CALL serv.registerOutputRequestHandler("OutputRequestHandler")
FUNCTION OutputRequestHandler(out) DEFINE out Xml.DomDocument DEFINE ind INTEGER DEFINE node Xml.DomNode DEFINE copy Xml.DomNode DEFINE tmp Xml.DomNode DEFINE parent Xml.DomNode DEFINE name STRING DEFINE list Xml.DomNodeList # Change output parameter below myrecord in uppercase # before sending back to the client LET list = out.SelectByXPath( "//SOAP:Envelope/SOAP:Body/fjs:EchoDOCRecordResponse/fjs:myrecord/*", "SOAP","http://schemas.xmlsoap.org/soap/envelope/", "fjs","http://www.mycompany.com/webservices") FOR ind = 1 TO list.getCount() LET node = list.getItem(ind) LET parent = node.getParentNode() LET name = node.getLocalName() LET copy = out.createElementNS(node.getPrefix(),name.toUpperCase(), node.getNamespaceURI()) LET tmp = node.getFirstChild() LET tmp = tmp.clone(true) CALL copy.appendChild(tmp) CALL parent.replaceChild(copy,node) END FOR RETURN out END FUNCTION
If NULL is return from the callback function, a SOAP fault will be sent and the ProcessServices() returns error code -19.