SET-CALLBACK-PROCEDURE is the way.
You need to do something like this (setRequestSessionHandler is the name of the procedure so it can be whatever you want) before you RUN the SOAP-call:
hp:SET-CALLBACK-PROCEDURE("REQUEST-HEADER", "setRequestSessionHeader").
The request-callback has two input and two output parameters (names taken from the documentation, they can be called anything as long as input/output and datatype is correct):
DEFINE OUTPUT PARAMETER hSOAPHeader AS HANDLE NO-UNDO.
DEFINE INPUT PARAMETER cOperationNamespace AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER cOperationLocalName AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER plDeleteOnDone AS LOGICAL NO-UNDO.
hSOAPHeader — A handle to a SOAP header object that encapsulates the header of the SOAP message
that is about to be sent (request header) or that has just been received (response header). In a response
header handler, the SOAP header object has no content if the NUM-HEADER-ENTRIES attribute on the
object handle returns the value 0; otherwise it contains one or more SOAP header entries. In a request
header handler, this is an OUTPUT parameter, therefore if the outgoing SOAP message requires a SOAP
header, you must either build a SOAP header for this parameter to reference or provide an existing SOAP
header saved from a previous response callback.
cOperationNamespace — Contains the namespace portion of the operation's qualified name. Use this
parameter together with the cOperationLocalName parameter if you need to identify the operation for
which the SOAP message is being sent or received.
cOperationLocalName — Contains the local-name portion of the operation's qualified name. Use this
parameter together with the cOperationNamespace parameter if you need to identify the operation for
which the SOAP message is being sent or received.
lDeleteOnDone — (Request callback only) Tells OpenEdge to delete the SOAP header object and all of
the parsed XML after the SOAP header has been inserted into the out-bound SOAP message
This is what I do to mimic WS-Security, not exactly what you need and also quite a lot of code. You should be able to "mine it" for whatever you need.
PROCEDURE setRequestSessionHeader :
/*------------------------------------------------------------------------------
Purpose:
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/
DEFINE OUTPUT PARAMETER phHeader AS HANDLE NO-UNDO.
DEFINE INPUT PARAMETER pcNamespace AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcLocalNS AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER plDeleteOnDone AS LOGICAL NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref1 AS HANDLE NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref2 AS HANDLE NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref3 AS HANDLE NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref4 AS HANDLE NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref5 AS HANDLE NO-UNDO.
DEFINE VARIABLE hXDocument AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASSecurity AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASUsernameToken AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASUserName AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASPassword AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASPasswordType AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASNonce AS HANDLE NO-UNDO.
DEFINE VARIABLE hWSUCreated AS HANDLE NO-UNDO.
DEFINE VARIABLE hADDMessageID AS HANDLE NO-UNDO.
DEFINE VARIABLE hADDTo AS HANDLE NO-UNDO.
DEFINE VARIABLE hADDAction AS HANDLE NO-UNDO.
DEFINE VARIABLE hAMA_SecurityHostedUser AS HANDLE NO-UNDO.
DEFINE VARIABLE hUserId AS HANDLE NO-UNDO.
DEFINE VARIABLE hTxt AS HANDLE NO-UNDO.
DEFINE VARIABLE hAttr AS HANDLE NO-UNDO.
DEFINE VARIABLE hRootNode AS HANDLE NO-UNDO.
/* Namespaces */
DEFINE VARIABLE cNSAddressing AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNSSecurity AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNSSecurityUtils AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNSAmaSec AS CHARACTER NO-UNDO.
DEFINE VARIABLE cMessageId AS CHARACTER NO-UNDO.
DEFINE VARIABLE cUserName AS CHARACTER NO-UNDO.
DEFINE VARIABLE cPasswordClear AS CHARACTER NO-UNDO.
DEFINE VARIABLE cPasswordDigest AS CHARACTER NO-UNDO.
DEFINE VARIABLE cCreated AS CHARACTER NO-UNDO.
DEFINE VARIABLE cAction AS CHARACTER NO-UNDO.
DEFINE VARIABLE cTo AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNonceB64 AS CHARACTER NO-UNDO.
DEFINE VARIABLE cOfficeId AS CHARACTER NO-UNDO.
DEFINE VARIABLE mNonce AS MEMPTR NO-UNDO.
ASSIGN
cNSAddressing = "http://www.w3.org/2005/08/addressing"
cNSSecurity = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
cNSSecurityUtils = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
cNSAmaSec = "http://illkeepthisasecret..."
cAction = "http://illkeepthisasecret..."
cTo = "https://noded1.production.webservices.amadeus.com/1ASIWIBNAIT".
ASSIGN
cUserName = "usernamegoeshere"
cOfficeId = "anothersettinggoeshere"
cPasswordClear = "passwordgoeshere".
/* Delete header when done! */
ASSIGN
plDeleteOnDone = TRUE.
CREATE SOAP-HEADER ghSoapHeader.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref1.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref2.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref3.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref4.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref5.
CREATE X-DOCUMENT hXDocument.
CREATE X-NODEREF hRootNode.
CREATE X-NODEREF hOASSecurity.
CREATE X-NODEREF hTxt.
CREATE X-NODEREF hOASUsernameToken.
CREATE X-NODEREF hOASPassword.
CREATE X-NODEREF hOASUserName.
CREATE X-NODEREF hOASNonce.
CREATE X-NODEREF hADDMessageID.
CREATE X-NODEREF hADDTo.
CREATE X-NODEREF hADDAction.
CREATE X-NODEREF hWSUCreated.
CREATE X-NODEREF hAMA_SecurityHostedUser.
CREATE X-NODEREF hUserId.
/* Not DATETIME-TZ! */
DEFINE VARIABLE dtZuluNow AS DATETIME NO-UNDO.
/* Genereate a random key and base64-encode it */
SET-SIZE(mNonce) = 16.
mNonce = GENERATE-RANDOM-KEY.
cNonceB64 = BASE64-ENCODE(mNonce).
/* Get time in UTC/GMT/ZULU/Timezone 0 */
dtZuluNow = DATETIME-TZ(NOW,0).
/* Manipulate the date string to fit specs... */
ASSIGN
cMessageId = LC(SUBSTRING(STRING(GENERATE-UUID), 8, 20))
cCreated = STRING(dtZuluNow, "9999-99-99THH:MM:SS") + ":000Z".
/* This is internal stuff for generating a digest... */
RUN generatePasswordDigest( mNonce, cCreated, cPasswordClear, OUTPUT cPasswordDigest).
/* Root node */
hXDocument:CREATE-NODE-NAMESPACE(hRootNode, "", "root", "element").
hXDocument:INSERT-BEFORE(hRootNode, ?).
/**** Addressing ****/
/* MessageID */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref1).
hXDocument:CREATE-NODE-NAMESPACE(hADDMessageID, cNSAddressing, "MessageID", "ELEMENT").
hRootNode:APPEND-CHILD(hAddMessageID).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cMessageId.
hADDMessageId:APPEND-CHILD(hTxt).
hSoapHeaderEntryref1:SET-NODE(hADDMessageID).
/* Action */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref2).
hXDocument:CREATE-NODE-NAMESPACE(hADDAction, cNSAddressing, "Action", "ELEMENT").
hRootNode:APPEND-CHILD(hADDAction).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cAction.
hADDAction:APPEND-CHILD(hTxt).
hSoapHeaderEntryref2:SET-NODE(hADDAction).
/* To */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref3).
hXDocument:CREATE-NODE-NAMESPACE(hADDTo, cNSAddressing, "To", "ELEMENT").
hRootNode:APPEND-CHILD(hADDTo).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cTo.
hADDTo:APPEND-CHILD(hTxt).
hSoapHeaderEntryref3:SET-NODE(hADDTo).
/**** Security ****/
/* Root node */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref4).
hXDocument:CREATE-NODE-NAMESPACE(hOASSecurity, cNSSecurity, "Security", "ELEMENT").
hRootNode:APPEND-CHILD(hOASSecurity).
/* UserNameToken node */
hXDocument:CREATE-NODE-NAMESPACE(hOASUsernameToken, cNSSecurity, "UsernameToken", "ELEMENT").
hOASUsernameToken:SET-ATTRIBUTE("Id", "UsernameToken-1").
hOASSecurity:INSERT-BEFORE(hOASUsernameToken, ?).
/* Username */
hXDocument:CREATE-NODE-NAMESPACE(hOASUserName, cNSSecurity, "Username", "ELEMENT").
hRootNode:APPEND-CHILD(hOASUserName).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cUserName.
hOASUserName:APPEND-CHILD(hTxt).
hOASUsernameToken:APPEND-CHILD(hOASUserName).
/* Nonce */
hXDocument:CREATE-NODE-NAMESPACE(hOASNonce, cNSSecurity, "Nonce", "ELEMENT").
hOASNonce:SET-ATTRIBUTE("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary").
hOASUsernameToken:APPEND-CHILD(hOASNonce).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cNonceB64.
hOASNonce:APPEND-CHILD(hTxt).
/* Password hash */
hXDocument:CREATE-NODE-NAMESPACE(hOASPassword, cNSSecurity, "Password", "ELEMENT").
hOASPassword:SET-ATTRIBUTE("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest").
hOASUsernameToken:APPEND-CHILD(hOASPassword).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cPasswordDigest.
hOASPassword:APPEND-CHILD(hTxt).
/* Created - timestamp */
hXDocument:CREATE-NODE-NAMESPACE(hWSUCreated, cNSSecurityUtils, "Created", "ELEMENT").
hOASUsernameToken:APPEND-CHILD(hWSUCreated).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cCreated.
hWSUCreated:APPEND-CHILD(hTxt).
hSoapHeaderEntryref4:SET-NODE(hOASSecurity).
/**** AMA_SecurityHostedUser ****/
/* Root node */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref5).
hXDocument:CREATE-NODE-NAMESPACE(hAMA_SecurityHostedUser, cNSAMASec, "AMA_SecurityHostedUser", "ELEMENT").
hRootNode:APPEND-CHILD(hAMA_SecurityHostedUser).
/* UserID */
hXDocument:CREATE-NODE-NAMESPACE(hUserID, cNSAMASec, "UserID", "ELEMENT").
hUserID:SET-ATTRIBUTE("AgentDutyCode", "SU").
hUserID:SET-ATTRIBUTE("RequestorType", "U").
hUserID:SET-ATTRIBUTE("PseudoCityCode", cOfficeId).
hUserID:SET-ATTRIBUTE("POS_Type", "1").
hAMA_SecurityHostedUser:APPEND-CHILD(hUserID).
hSoapHeaderEntryref5:SET-NODE(hAMA_SecurityHostedUser).
/* Output the header */
phHeader = ghSoapHeader.
/* Cleanup */
IF VALID-HANDLE(hOASSecurity) THEN
DELETE OBJECT hOASSecurity.
IF VALID-HANDLE(hOASUsernameToken) THEN
DELETE OBJECT hOASUsernameToken.
IF VALID-HANDLE(hOASUserName) THEN
DELETE OBJECT hOASUserName.
IF VALID-HANDLE(hOASPassword) THEN
DELETE OBJECT hOASPassword.
IF VALID-HANDLE(hADDMessageID) THEN
DELETE OBJECT hADDMessageID.
IF VALID-HANDLE(hOASNonce) THEN
DELETE OBJECT hOASNonce.
IF VALID-HANDLE(hTxt) THEN
DELETE OBJECT hTxt.
IF VALID-HANDLE(hADDTo) THEN
DELETE OBJECT hADDTo.
IF VALID-HANDLE(hWSUCreated) THEN
DELETE OBJECT hWSUCreated.
IF VALID-HANDLE(hADDAction) THEN
DELETE OBJECT hADDAction.
IF VALID-HANDLE(hXDocument) THEN
DELETE OBJECT hXDocument.
IF VALID-HANDLE(hRootNode) THEN
DELETE OBJECT hRootNode.
IF VALID-HANDLE(hSoapHeaderEntryRef1) THEN
DELETE OBJECT hSoapHeaderEntryRef1.
IF VALID-HANDLE(hSoapHeaderEntryRef2) THEN
DELETE OBJECT hSoapHeaderEntryRef2.
IF VALID-HANDLE(hSoapHeaderEntryRef3) THEN
DELETE OBJECT hSoapHeaderEntryRef3.
IF VALID-HANDLE(hSoapHeaderEntryRef4) THEN
DELETE OBJECT hSoapHeaderEntryRef4.
IF VALID-HANDLE(hSoapHeaderEntryRef5) THEN
DELETE OBJECT hSoapHeaderEntryRef5.
IF VALID-HANDLE(hAMA_SecurityHostedUser) THEN
DELETE OBJECT hAMA_SecurityHostedUser.
IF VALID-HANDLE(hUserId) THEN
DELETE OBJECT hUserId.
END.