Operations needing session key to be be passed in odata request
When session key has to be passed for every soap operation, the following can be done in order to achieve this.
The first step would be to get the session key from a login operation.
The user must provide the credentials as input to login soap operation. This will return session key if login is successful.
The input parameters (username/password) to login operation can be passed via custom script
This session key is passed as odata request header which can be fetched in custom script and set to exchange header or the cxf payload
Steps from Design Time tool
- Create an OData Service Implementation Project
- Create an OData Model for login operation, which can have property SessionKey
3. Right click on odatasvc and choose Select data source
4. Select the entity set and choose the query CRUD operation. Select the data source SOAP Service.
5. Specify the wsdl file and choose the login operation from the list of soap operations and click on finish
6. Right click on Query and select Define Custom Code
Select the script type
7. Create a hashMap specifying username and password in the custom script’s processRequestData function
function processRequestData(message) {
importPackage(java.util);
importPackage(org.apache.olingo.odata2.api.processor);
importPackage(com.sap.gateway.ip.core.customdev.logging);
var context = message.getHeaders().get("odatacontext");
var username = context.getRequestHeaders().get("username").get(0); // Read the parameters from odata header request
var password = context.getRequestHeaders().get("password").get(0);
childMap = new LinkedHashMap();
childMap.put("username", username);
childMap.put("password", password);
message.setBody(childMap);
return message;
}
f the odata request is https://localhost:8083/gateway/odata/SAP/SAMPLE;v=1/LoginSet,
Then the request payload looks like
<soapenv:Body>
<aut:LogIn>
<UserName><username></UserName>
<Password><password></Password>
</aut:LogIn>
</soapenv:Body>
8. Right click on Query and select Define Response Mapping
9. Do the mapping as below
10. Right Click on Project and select Generate and Deploy Integration Content. This will deploy the bundle.
Now fire an OData Request https://localhost:8083/gateway/odata/SAP/SAMPLE;v=1/LoginSet on the browser and response will give a session key.
11. Modify the same project created above. Add another entity type in odata model
12. Right click on odatasrv and Select Data source
13. Select the newly added entity set and choose any CRUD operation
14. Select the wsdl and operation
15. Right Click on CRUD operation and select Define custom Code like done before
16. The custom code must fetch the session key obtained in previous login operation from the request header and set this to exchange header.
The odata request header looks like
function processRequestData(message) {
importPackage(org.apache.olingo.odata2.api.processor);
var context = message.getHeaders().get("odatacontext");
var sessionId = context.getRequestHeaders().get("TargetSession"); // TargetSession is the header name sent in request
var id = "JSESSIONID="+sessionId.get(0);
message.setHeader("Cookie",id);
return message;
}
Note: Some web services need session Key to be part of cxfPayload header.Then the function processRequestXML in the custom script must have the below code
function processRequestXML(message) {
importPackage(org.apache.olingo.odata2.api.processor);
var context = message.getHeaders().get("odatacontext");
var sessionId = context.getRequestHeaders().get("TargetSession"); // Target session is the header name sent in odata request
importPackage(org.apache.camel.component.cxf);
importPackage(java.util);
importPackage(org.apache.cxf.helpers);
importPackage(java.io);
importPackage(javax.xml.soap);
importPackage(javax.xml.namespace);
importPackage(java.lang);
importPackage(org.apache.cxf.binding.soap);
importPackage(org.w3c.dom);
rootElement = DOMUtils.readXml(new ByteArrayInputStream(new StringBuilder()).
append("<tns:sessionKey xmlns:tns=\"http://namespace\">").
append(sessionId).append("</tns:sessionKey>").
toString().getBytes())).getDocumentElement();
var payload = message.getBody(CxfPayload);
payload.getHeaders().add(new SoapHeader(new javax.xml.namespace.QName("http://namespace",
"sessionKey"), rootElement));message.setBody(payload);
return message;
}
The request payload looks like
<soapenv:Header>
<tns:sessionKey xmlns:tns="http://namespace">
0xxffjjlki3456
</tns:sessionKey>
</soapenv:Header>
<soapenv:Body>
<objNamespace:getList xmlns:objNamespace=”http://objectNamespace”>
</objNamespace:getList>
</soapenv:Body>
17. Right click on CRUD operation and select Define response mapping and do the mapping like before
18. Right click on Project and click on Generate and Deploy Integration Content
Now fire an OData Request https://localhost:8083/gateway/odata/SAP/SAMPLE;v=1/ListSet specifying the header
19. Some web services may need to send username, password as part of exchange headers. In this case the username:password must be encoded and this value must be set to exchange header. The header name will be Authorization and value will be Basic <Encoded Text>
The request payload will be
<soapenv:Body>
<xyz:findListOfElements>
<arg0>
<MaxResults/>
<adjustDates></adjustDates>
</arg0>
</xyz:findListOfElements>
</soapenv:Body>
The custom code script for the same is
function processRequestData(message) {
importPackage(java.util);
var parentMap = new HashMap();
var childMap = new HashMap();
childMap.put("MaxResults", "");
childMap.put("adjustDates", "");
parentMap.put(childMap);
message.setBody(parentMap);
message.setHeader("Authorization", "Basic <Encoded Text>");
return message;
}
Note: in the above script, header value is hardcoded. To avoid this username, password can sent as filter expressions in odata URI and value can be encoded in the script.
Or, encode the username/password and send the encoded value as a request header parameter, which can be fetched in the script file and set to message header.
20. Some web services require attributes to be added to the CxfPayload elements.
The request payload will be
<soapenv:Body>
<xyz:LoginCustomerRequest origin="SoapUI" traceNo="A123456789" repeat="false">
<identification>+6287880946389</identification>
<credential>123123</credential>
<identificationType>0</identificationType
<credentialType>0</credentialType>
</xyz:LoginCustomerRequest>
</soapenv:Body>
The custom code script for the same is
function processRequestData(message) {
importPackage(java.util);
importPackage(org.apache.olingo.odata2.api.processor);
var childMap = new LinkedHashMap();
childMap.put("identification", "+6281945554369");
childMap.put("credential", "112233");
childMap.put("identificationType", "0");
childMap.put("credentialType", "0");
message.setBody(childMap);
return message;
}
function processRequestXML(message) {
importPackage(org.apache.camel.component.cxf);
importPackage(org.apache.cxf.helpers);
importPackage(java.io);
var str = message.getBody();
var rootElement = DOMUtils.readXml(new ByteArrayInputStream(str.getBytes())).
getDocumentElement();
var payload = (CxfPayload)(message.getBody(CxfPayload));
rootElement.setAttribute("origin", "SoapUI");
rootElement.setAttribute("traceNo", "UI6ot772");
rootElement.setAttribute("repeat", "false");
payload.getBody().remove(0);
payload.getBody().add(rootElement);
message.setBody(payload);
return message;
}
Hi Ramya,
Some of the images are not visible, could you insert it once again.
Thanks
-Stan
Hi ..
For the above request I want to pass the origin and TraceNo dynamically..that means i don't want to keep statically please help me
Hi,
If you want to pass any parameter dynamically, you can pass it via headers or as an OData filter.
You can read this value (if set as header) in the custom script using methods message.getHeaders() as described in the blog.
If it is set as filter you can read the value as described in the blog
http://scn.sap.com/community/developer-center/mobility-platform/blog/2014/10/29/how-to-handle-filters-in-soap-operations
Regards,
Ramya
Thanks a lot for this blog. It helped us a lot for passing SOAP Header parameters.