如何从iSeries COBOL调用Web服务?

时间:2011-12-19 22:56:13

标签: c web-services ibm-midrange cobol

我们需要能够从在iSeries LPAR(V6R1)上运行的COBOL代码调用内部Web服务。我完成了一个完整的例子,我可以在网上找到here。因此,我的下一步是尝试重复此过程并调用我们现有的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;
}

我可以在调试模式下设置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.          

当它以这种方式编码时,我得到一个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.

1 个答案:

答案 0 :(得分:4)

  

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

我是COBOL的人,但不是iSeries。注意事项。

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

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

... FWIW