如何从iSeries COBOL调用Web服务?

Pau*_*l G 5 c cobol web-services ibm-midrange

我们需要能够从在iSeries LPAR(V6R1)上运行的COBOL代码调用内部Web服务.我经历了一个完整的例子,我能在网上找到的工作在这里.因此,我的下一步是尝试重复此过程并调用我们现有的Web服务之一.

我使用QSH的WSDL2WS命令生成C客户端存根.我修改了示例COBOL客户端程序并尝试调用我的Web服务.我遇到的问题似乎与示例C客户端方法返回指针并且COBOL代码将它们分配给指针的事实有关.我怀疑我的COBOL代码中的错误是我的问题的根源,因为WSDL2WS为我的Web服务方法创建的C方法返回一个简单的xsdc_string而不是指向自定义结果类型的指针:

xsdc__string TestUnsuccessfulMessage(AXISCHANDLE stub)
{
    AXISCHANDLE call = axiscStubGetCall(stub);
    xsdc__string Ret = NULL;

    axiscCallSetSoapFaultNamespace(call, "http://myserver/PSItemMaintenance/ItemMaintenanceService.svc");


    // ======================================================================
    // Initialize client engine, set SOAP version, SOAPAction, operation, etc.
    // ======================================================================

    if (AXISC_SUCCESS != axiscCallInitialize(call, C_DOC_PROVIDER ))
        return Ret;

    if (NULL==axiscCallGetTransportProperty(call,"SOAPAction",0))
        axiscCallSetTransportProperty(call,AXISC_SOAPACTION_HEADER , "http://tempuri.org/IItemMaintenanceService/TestUnsuccessfulMessage");

    axiscCallSetSOAPVersion(call, SOAP_VER_1_1);
    axiscCallSetOperation(call, "TestUnsuccessfulMessage", "http://tempuri.org/");

    // ======================================================================
    // Apply SSL configuration properties and user-set SOAP headers.
    // ======================================================================

    axiscStubIncludeSecure(stub);
    axiscStubApplyUserPreferences(stub);


    // ======================================================================
    // Invoke web service, send/receive operation. Handle output parameters, if any.
    // ======================================================================

    if (AXISC_SUCCESS == axiscCallSendAndReceive(call))
    {
        if(AXISC_SUCCESS == axiscCallValidateMessage(call, "TestUnsuccessfulMessageResponse", "http://tempuri.org/", true_))
        {
            Ret = axiscCallGetElementAsString(call, "TestUnsuccessfulMessageResult", 0);
        }

        axiscStubCheckForExtraneousElements(stub);
    }
    axiscCallUnInitialize(call);
    return Ret;
}
Run Code Online (Sandbox Code Playgroud)

我可以在调试模式下设置Web服务,当我运行调用COBOL和C模块的程序时,可以看到来自iSeries的调用.我还可以看到我返回一个简单的字符串值.

当COBOL程序尝试获取返回值并使用它时,问题就出现了.我相信COBOL代码的相关位是:

LINKAGE PROCEDURE FOR "TestSuccessfulMessage"
                 USING ALL DESCRIBED    

LINKAGE SECTION.                     
 01 LookupResult         PIC X(1000).  

CALL PROCEDURE "TestSuccessfulMessage"
 USING BY VALUE STUB              
 RETURNING LookupResult.          
Run Code Online (Sandbox Code Playgroud)

当它以这种方式编码时,我得到一个MCH3601.如果我返回一个指针,然后将地址设置为LookupResult,我最终得到一个空值.

我希望我在某个地方错过了一个小细节.我的COBOL经验非常少.我只是想创建一个参考应用程序作为我们公司内另一个团队的概念证明.任何帮助,或建议尝试什么将不胜感激.我可以提供更多代码.

更新:我尝试将LookupResult声明移动到工作存储中.虽然这消除了MCH3601错误,但我的显示器中只有一堆垃圾数据.我可以在数据中看到有关我的iSeries会话(即deviceID等)的信息.

我还尝试将LookupResult留在链接部分并在工作存储中创建指针.然后我添加了"LookupResult到ResultPointer的SET地址".同样,调用没有错误地结束,但是当我显示LookupResult时,我得到了垃圾数据.但是,如果我直接返回LookupResult,它与返回的数据不同.我可以在这些数据中看到SOAP信封的各个部分.

最后: 我必须做的所有更改都在COBOL代码中.以下是相关部分:

WORKING-STORAGE SECTION.              
01 Endpoint             PIC X(100).   
01 STUB                 USAGE POINTER.
01 ResultPointer        USAGE POINTER.

LINKAGE SECTION.                      
01 pszEndpoint          PIC X(100).   
01 LookupResult         PIC X(7).   

CALL PROCEDURE "TestSuccessfulMessage"       
     USING BY VALUE STUB                     
     RETURNING INTO ResultPointer.           

SET Address of LookupResult TO ResultPointer.
Run Code Online (Sandbox Code Playgroud)

csc*_*eid 4

如果我返回一个指针,然后将地址设置为 LookupResult,我最终会得到一个空值。

我是一个 COBOL 人,但不是 iSeries 人。买者自负。

如果 xsdc__string 解析为指针,那么您的 COBOL 代码应该为 CALL 的 RETURNING 部分提供一个 POINTER 类型的变量。也许 C 函数实际上返回 NULL,代码当然允许它 - 也许 axiscCallInitialize 没有返回 AXISC_SUCCESS。

至少在 z/OS 上,您希望 COBOL 指针变量位于工作存储或本地存储中,然后您将 SET ADDRESS OF LookupResult TO 该指针变量。我认为这不会仅仅因为您使用不同的机器架构而改变。

...FWIW