Back to Contents


Fix 2.10 to 2.11 WSDL generation issue


Overview

This document explains how to convert a WSDL generated from Genero 2.11 and later, to a WSDL as generated in Genero 2.10.

Since Genero 2.11, each 4GL variable generates a associated named complexType in the WSDL and references it. Notice that this does not impact the web service at all, but some tools will then generate additional client stubs to follow the WSDL definition with the name of such complexType. This means that a client program written from a WSDL generated in 2.10 must be reviewed if it uses now a WSDL generated in 2.11 or later.
If you do not want to modify your application, you can use following program that will remove the named complexType and add the unamed equivalent as child node of the parameter variable of all web service operations, so in other words, as if the WSDL would have been generated in 2.10.

Back to the top


WSDL conversion tool

This program reads a WSDL, looks for all named complexType used in all the web operation parameters and modifies them in order to have unamed complexType instead.

IMPORT XML
MAIN
    DEFINE
        doc xml.DomDocument,
        list, elist, tlist xml.DomNodeList,
        node, enode, nnode xml.DomNode,
        i, j, k, idx INT,
        ename, tname STRING

    IF num_args() <> 1 THEN
        CALL display_help()
        RETURN 0
    END IF

    TRY
        LET doc = xml.DomDocument.Create()
        CALL doc.setFeature("whitespace-in-element-content",FALSE)
        CALL doc.load(arg_val(1))
        # get the list of input/output message
        # check if their names (x) are defined as elements with types (y)
        # if yes then
        # copy the complextype y definition to element name x
        # and remove the complexe type y definition
        # for example:
        # message
        # <wsdl:message name="is_OKIn">
        # <wsdl:part name="parameters" element="fjs:is_OKRequest" />
        # </wsdl:message>
        # <wsdl:message name="is_OKOut">
        # <wsdl:part name="parameters" element="fjs:is_OKResponse" />
        # </wsdl:message>
        # element
        # <xsd:element name="is_OKResponse" type="s1:is_OKResponse_is_OKResponse" />
        # type
        # <xsd:complexType name="is_OKRequest_is_OKRequest">
        LET list = doc.selectByXPath("//wsdl:part[@name='parameters']/@element","wsdl","http://schemas.xmlsoap.org/wsdl/")
        IF list IS NULL THEN 
            DISPLAY "Nothing to convert."
        END IF
        FOR i=1 TO list.getCount()
            LET node = list.getItem(i)
            LET ename = node.getNodeValue()
            LET idx = ename.getIndexOf(":",1)
            IF idx > 0 THEN 
                LET ename = ename.subString(idx+1,ename.getLength())
            END IF
            # get the element
            LET elist = doc.selectByXPath("//xsd:element[@name='" || ename || "']","xsd","http://www.w3.org/2001/XMLSchema")
            IF elist IS NOT NULL THEN
                FOR j=1 TO elist.getCount()
                    LET enode = elist.getItem(j)
                    LET tname = enode.getAttribute("type")
                    CALL enode.removeAttribute("type")
                    LET idx = tname.getIndexOf(":",1)
                    IF idx > 0 THEN 
                        LET tname = tname.subString(idx+1,tname.getLength())
                    END IF
                    # get the type
                    LET tlist = doc.selectByXPath("//xsd:complexType[@name='" || tname || "']","xsd","http://www.w3.org/2001/XMLSchema")
                    IF tlist IS NOT NULL THEN
                        FOR k=1 TO tlist.getCount()
                            LET node = tlist.getItem(k)
                            LET nnode = node.clone(TRUE)
                            CALL nnode.removeAttribute("name")
                            CALL enode.appendChild(nnode)
                        END FOR
                    END IF
                    FOR k=1 TO tlist.getCount()
                        LET node = tlist.getItem(k)
                        LET nnode = node.getParentNode()
                        CALL nnode.removeChild(node)
                    END FOR
                END FOR
            END IF            
        END FOR
        CALL doc.setFeature("format-pretty-print",TRUE)
        CALL doc.save("result.wsdl")
        DISPLAY "Document is saved in result.wsdl"
    CATCH
        DISPLAY "ERROR[" || STATUS || "]"
        FOR i=1 TO doc.getErrorsCount()
          DISPLAY "[", i, "] ", doc.getErrorDescription(i)
        END FOR
    END TRY
END MAIN 

FUNCTION display_help()
    DISPLAY "Usage: fglrun " || arg_val(0) || " wsdlfile"
END FUNCTION

Example of usage:

$ fglrun Convert Genero2_21.wsdl
$ Document is saved in result.wsdl

Back to the top