2011-12-19 13 views
5

Dobbiamo essere in grado di chiamare un servizio Web interno dal codice COBOL in esecuzione su un iSeries LPAR (V6R1). Ho lavorato attraverso l'unico esempio completo che sono riuscito a trovare online here. Quindi, il mio prossimo passo era provare a ripetere il processo e chiamare uno dei nostri servizi web esistenti.Come si chiama un servizio Web da iSeries COBOL?

Ho utilizzato il comando WSDL2WS da QSH per generare gli stub client C. Ho modificato il programma client COBOL di esempio e ho tentato una chiamata al mio servizio web. Il problema che sto eseguendo sembra essere correlato al fatto che i metodi client C di esempio restituiscono i puntatori e il codice COBOL li sta assegnando ai puntatori. Ho il sospetto che un errore nel mio codice COBOL è la radice del mio problema, perché il metodo C che quella WSDL2WS creato per il mio metodo di servizio Web restituisce un semplice xsdc_string non un puntatore a un tipo di risultato personalizzato:

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; 
} 

I può configurare il servizio Web in modalità di debug e può vedere la chiamata da iSeries quando eseguo il programma che chiama i moduli COBOL e C. Posso anche vedere che sto tornando indietro un valore di stringa semplice.

Il problema si presenta quando il programma COBOL tenta di prendere il valore restituito e usarlo. Credo che i bit rilevanti del codice COBOL sono:

LINKAGE PROCEDURE FOR "TestSuccessfulMessage" 
       USING ALL DESCRIBED  

LINKAGE SECTION.      
01 LookupResult   PIC X(1000). 

CALL PROCEDURE "TestSuccessfulMessage" 
USING BY VALUE STUB    
RETURNING LookupResult.   

ho un MCH3601 quando è codificato in questo modo. Se torno a un puntatore e poi l'indirizzo a LookupResult, finisco con un valore nullo.

Spero che manchi solo un piccolo dettaglio da qualche parte. Ho davvero poca esperienza COBOL. Sto solo cercando di creare un'app di riferimento come prova del concetto per un altro team all'interno della nostra azienda. Qualsiasi aiuto o suggerimento su cosa provare sarebbe apprezzato. Posso fornire più codice.

Aggiornamento: Ho provato a spostare la dichiarazione LookupResult nella memoria di lavoro. Mentre questo ha eliminato l'errore MCH3601, ho appena ricevuto un mucchio di dati inutili sul mio display. Riesco a vedere pezzi di informazioni sulla mia sessione iSeries (cioè ID dispositivo, ecc.) All'interno dei dati.

Ho anche provato a lasciare LookupResult nella sezione di collegamento e creare un puntatore nella memoria di lavoro. Quindi ho aggiunto un "SET Address of LookupResult TO ResultPointer". Ancora una volta, la chiamata è terminata senza errori, ma quando visualizzo LookupResult ottengo dati inutili. Tuttavia, è diverso dai dati che vengono restituiti se torno direttamente a LookupResult. Posso vedere pezzi della busta SOAP in questi dati.

Finale: Tutte le modifiche che ho dovuto apportare erano nel codice COBOL. Qui ci sono i pezzi rilevanti:

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. 

risposta

4

Se torno in un puntatore e quindi impostare l'indirizzo a LookupResult, ho alla fine con un valore nullo.

Sono una persona COBOL, ma non su iSeries. Caveat emptor.

Se xsdc__string si risolve in un puntatore, il codice COBOL deve avere una variabile di tipo POINTER per la parte RESTUALE della CHIAMATA. Forse la funzione C sta infatti restituendo NULL, il codice certamente lo consente - forse axiscCallInitialize non sta restituendo AXISC_SUCCESS.

Almeno su z/OS, si desidera che la variabile del puntatore COBOL si trovi in ​​Storage di lavoro o Archiviazione locale, quindi VERRERE SET ADDRESS DI LookupResult su quella variabile del puntatore. Presumo che non cambi solo perché sei su un'architettura di macchine diversa.

... FWIW

+0

Grazie. Ho provato a utilizzare un puntatore e il comando SET ADDRESS OF, ma al momento credo che la mia dichiarazione del puntatore fosse nella sezione linkage. Proverò a spostarlo sullo storage funzionante. Ho anche inserito il codice C in modalità di debug. Posso vedere che Ret inizia come NULL, ma dopo la chiamata ha un valore, che nel debugger iSeries mostra Ret = SPP: DA1A1DDC05014450. –

+1

Sto considerando questa risposta perché contiene le informazioni sul cambio di codice che dovevo apportare. Ho creato una variabile puntatore nella memoria di lavoro. Ho cambiato la chiamata per utilizzare la sintassi "RETURNING INTO MyPointer" e ho usato il comando Set Address Of come suggerito. Grazie ancora. –

Problemi correlati