Variable replacement in XML payload using KVM

I am getting a username and pwd in XML request payload. I need to assign a values for 'username' and 'pwd' values in Apigee.

we can do this in multiple ways,

1) Using extract variable

2) using soap template.

But I need to use KVM, can we do that ??

Solved Solved
1 8 820
1 ACCEPTED SOLUTION

HI , I agree above comments helped me to think on such a way to get solution. As Dino said I did not use flow callouts or Java callout.

1) I used a extract variable policy to extract variables from my XML payload.

2) The moment I extracted , All the flow variables will be available. I used assin message policy to retrieve KVM's and constructed a xml request payload to the backend by using XML template (https://community.apigee.com/questions/34012/replacing-xml-node-values-with-custom-values.html).

This worked for me.

View solution in original post

8 REPLIES 8

Not applicable

What actually you want to do?

You want request payload extraction. KVM is used for the purpose of storage of information. The purpose is different. You should use Extract variable policy.

I need to extract variables from KVM, and assign it to the XML request payload. how do I do that ?

Ok, got it. Yes, you can store in kvm. If you are using encrypted kvm then prefix private needs to be appended to the assignment variable in KVM.

As this is username and password I would suggest to use encrypted kvm.

Then you can use assign message policy to construct the XML payload.

Multiple ways to do it.

A Good one is to use AssignMessage and a hardcoded template. Here's how it would work.

  1. Read the values from KVM. The examples that follow assume this data is loaded into context variables named private.username and private.password.
  2. Use an "AssignMessage", specifying a template for the payload, which includes references to those variables.

    <AssignMessage name='AM-Request-explicit'>
      <AssignVariable>
        <Name>formatString1</Name>
        <Value>yyyy-MM-dd'T'HH:mm:ss'Z'</Value>
      </AssignVariable>
      <AssignVariable>
        <Name>formattedTime</Name>
        <Template>{timeFormatUTCMs(formatString1,client.received.end.timestamp)}</Template>
      </AssignVariable>
      <Set>
        <Payload contentType='application/xml'>
    <soap:Envelope xmlns:ns1="urn://C593C08C-A6D3-4806-A3C6-BE232825D97A"
                   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
     <soap:Header>
      <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/06/secext">
       <wsse:UsernameToken wsu:Id="element-123"
           xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility">
        <wsse:Username>{private.username}</wsse:Username>
        <wsse:Password Type="wsse:PasswordText">{private.password}</wsse:Password>
        <wsu:Created>{formattedTime}</wsu:Created>
       </wsse:UsernameToken>
      </wsse:Security>
     </soap:Header>
      <soap:Body>
       <ns1:Operation1 />
      </soap:Body>
    </soap:Envelope>
    </Payload>
      </Set>
      <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
      <AssignTo>request</AssignTo>
    </AssignMessage>
    	

Other options include: XSL, or a Java callout to insert XML nodes into an existing document. Those seem more complicated.

A final option that might be attractive is... storing the XML template file into a "template" resource and then referencing that from within assign message. It's basically a twist on the first option. It looks like this:

<AssignMessage name='AM-Request-explicit'>
  <AssignVariable>
    <Name>formatString1</Name>
    <Value>yyyy-MM-dd'T'HH:mm:ss'Z'</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>formattedTime</Name>
    <Template>{timeFormatUTCMs(formatString1,client.received.end.timestamp)}</Template>
  </AssignVariable>
  <Set>
    <!-- this refers to a template resource. -->


    <!-- This uses the designated file as a message
         template, and fills in references to variables surrounded by curlies.
         If there are no curlies, then... it just includes the file as is.
    -->

    <Payload contentType='application/xml' resourceURL='template://request1.xml.tmpl'/>
  </Set>

  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
  <AssignTo>request</AssignTo>
</AssignMessage>

And the content of the template file is

<soap:Envelope xmlns:ns1="urn://C593C08C-A6D3-4806-A3C6-BE232825D97A"
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Header>
  <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/06/secext">
   <wsse:UsernameToken wsu:Id="element-123"
       xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility">
    <wsse:Username>{private.username}</wsse:Username>
    <wsse:Password Type="wsse:PasswordText">{private.password}</wsse:Password>
    <wsu:Created>{formattedTime}</wsu:Created>
   </wsse:UsernameToken>
  </wsse:Security>
 </soap:Header>
  <soap:Body>
   <ns1:Operation1 />
  </soap:Body>
</soap:Envelope>
<br>

..and that thing gets included in the proxy bundle as /apiproxy/resources/template/request1.xml.tmpl.

You may notice that I use AssignVariable in the AssignMessage policies. Those AssignVariable elements run before the Set element, and prepares a formatted timestring for injection into the right spot in the WSSE header.

-----

If the XML document is inbound on the request, then you don't want to use this AssignMessage / template approach. For that you want to use XSL, or.... if you are not XSL savvy, then you could use a callout like this one to solve the problem. It was designed specifically for that purpose.

Hi, Thanks for answering.

I could be able to use KVM and pass variables successfully. but I am also trying to construct whole xml payload here right. I cannot able to replace variables in the body.

My payload looks like this,

<?xml version="1.0" encoding="UTF-8"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="AM.AddUsernamePwd">
   <DisplayName>AM.AddUsernamePwd</DisplayName>
   <Properties />
   <Set>
      <Payload contentType="text/xml">
         <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:orac="http://oracle.e1.bssv.JPR01000/">
            <soapenv:Header>
               <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" soapenv:mustUnderstand="1">
                  <wsse:UsernameToken>
                     <wsse:Username>{private.Username}</wsse:Username>
                     <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">{private.Password}</wsse:Password>
                  </wsse:UsernameToken>
               </wsse:Security>
            </soapenv:Header>
            <soapenv:Body>
               <orac:addAddressBook>
                  <entityAddress>
                     <address>
                        <addressLine1>{123 Test Address}</addressLine1>
                        <city>{Louisville}</city>
                        <countryCode>{US}</countryCode>
                        <countyCode>{Louisville}</countyCode>
                        <postalCode>{40229}</postalCode>
                        <stateCode>{KY}</stateCode>
                     </address>
                  </entityAddress>
                  <entityName>{Louisville HP1}</entityName>
                  <entityTypeCode>{F}</entityTypeCode>
               </orac:addAddressBook>
            </soapenv:Body>
         </soapenv:Envelope>
      </Payload>
   </Set>
   <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
   <AssignTo createNew="false" transport="http" type="request" />
</AssignMessage>

COPY TO CLIPBOARD SELECT ALL

I cannot able to replace variables in the body.

Yes, what have you tried? You're showing me an XML document. Does that XML document arrive from the client in a request payload?

Or maybe it is static, and you're imagine it will be part of the API Proxy? Have you embedded that into an AssignMessage policy? Have you taken the approach that I described, loading that SOAP document in as a template?

Did you look at the callout I referenced?

Help me out here.

What have you tried? What is your feedback to the ideas I suggested?

Hi Dino,

I have added KVM to store username and pwd. And I am referring that under the Assign message. And also I am receiving body in the payload for that I created a Assign message (Please check above assign reply). Now I can able to replace "uaername" and "pwd" with KVM (encrypted) values but cannot replace variables in flower brackets with incoming variables in the request payload.

HI , I agree above comments helped me to think on such a way to get solution. As Dino said I did not use flow callouts or Java callout.

1) I used a extract variable policy to extract variables from my XML payload.

2) The moment I extracted , All the flow variables will be available. I used assin message policy to retrieve KVM's and constructed a xml request payload to the backend by using XML template (https://community.apigee.com/questions/34012/replacing-xml-node-values-with-custom-values.html).

This worked for me.