cancel
Showing results for 
Search instead for 
Did you mean: 

Cloud platform integration with OData - How to handle incoming $filter query parameter

virendra_raval
Explorer
0 Kudos

We have defined an iFlow that exposes an OData service and consumes a receiver OData service. We want to allow end user to query this iFlow OData service with a $filter query parameter. We want the iFlow to able to extract the $filter from the incoming url and pass that to the receiver OData service.

How do we do this?

We think that the solution involves something like this:

${header.filter} in “Custom Query Options” field of “Processing” tab in “OData Receiver” connection

But we don’t know what ${header} property to use and we can’t find any documentation that clearly identifies the available ${header} properties.

Any guidance in the matter is appreciated.

Accepted Solutions (1)

Accepted Solutions (1)

virendra_raval
Explorer

Hi all,

Good news! The issue was fixed when the following code added into the default groovy script right after Odata sender channel.

if(uriInfo.getFilter() != null){

def filter = uriInfo.getFilter().getExpressionString();

if(odataURI.size()!=0)

odataURI.append(urlDelimiter);

odataURI.append("\$filter=").append(filter);

log.logErrors(LogMessage.TechnicalError, "Filter value:"+filter);

}

Thereafter, added the ${Header.odataURI} into query options of OData receiver adapter.


0 Kudos

Thank you for adding your solution Virendra

WPGH_Christy
Explorer
0 Kudos

Hi Virendra,

I encountered the same issue with you.I also want to combine the parameters from Postman with some fixed query parameters set on the OData query options.But I don't know how to pass the query parameter of the postman to the OData query option.I tried the code you provided above but it always returned error to me,like below.

and below is my integration flow.

Could you provide the complete code of the groovy script to me?Thank you in advance!!

Regards,

Christy

saranya_baskaran2
Participant
0 Kudos

Hi All,

Please refer to the blog https://blogs.sap.com/2019/08/12/odata-service-in-cpi-for-beginners/#Query

It explains how each of the OData query options can be extracted and used as message header in the Integration flow.

BR
Saranya

Answers (9)

Answers (9)

sumanth171
Active Participant

Hello Andrew,

Earlier, I tried OData as sender and couldn't able to fetch the URL parameters. So I have changed the design to HTTP as sender for capturing the query Parameters as there is no design restriction for us.

If the OData adapter to be used for sure, then please use the header UriInfo header and then you can see the value of header as com.sap.gateway.core.ip.odata.OGWUriInfo@xyza123. Using groovy script we have to apply few methods on this class and fetch the filter paramter.

sumanth171
Active Participant

I have facing the same issue now. I have placed the iFlow in Trace mode and verified. There is no standard header available for accessing the query part in the incoming url.

So for an alternative I am using HTTP sender channel for fetching the query part. Now I can able to access the CamelHttpQuery header into another header variable in content modifier. I used groovy script to isolate only values I require and saved in a property and using in further steps.

0 Kudos

Hi Anil,

Good to hear you have it working with this method (-> http - Odata ->).

Thanks for the info.

Hi Virendra,

Glad to hear you have got the pulling of data and logging it working.

I'm not sure how to do the same with an Odata call (v4?), I assume it would add an extra layer of processing if it is possible, but it would take some time and testing to give a proper answer or suggestion.

I would recommend to open a incident.

Kind Regards

Hi Virendra,

It's best to open an incident with us now to get further assistance with this.

Best Regards

virendra_raval
Explorer

Hi Kevin,

We are now able to dump the content of header and properties into logs, however, from the logs, not able to find any key/variable which is responsible for capturing filter value passed through url. For example, the below is Header List details from the current OData Service iFlow.

null accept-language en-US,en;q=0.9,gu;q=0.8

ODataContext org.apache.olingo.odata2.core.ODataContextImpl@501b8ee3 odataEntity Customers ODataMethod GET_FEED odataURI null SAP_MessageProcessingLogID AFy_xY3nU4CZP0GUMwfhjwAyYXip scriptFile script2.gsh scriptFileType groovy UriInfo com.sap.gateway.core.ip.odata.OGWUriInfo@da8f72b x-forwarded-for 50.101.108.120

The same attempt to pass filter to a regular HTTP Integration Flow retrieves the below Header content which seems to pass the filter value correctly in the header as we can see the ID eq 'RAVAL' being captured in the CamelHttpQuery as seen below.

null CamelHttpMethod GET CamelHttpPath CamelHttpQuery $filter=ID%20eq%20%27RAVAL%27 CamelHttpUrl https://c0908-iflmap.hcisb.int.sap.eu2.hana.ondemand.com/http/pogo CamelServletContextPath /pogo SAP_MessageProcessingLogID AFy_bxZ9Qd5hRZKz6n53-3VDJF6c scriptFile POGO_script.gsh scriptFileType groovy

..wondering how do we get such element like CamelHttpQuery in case of OData Integration flow.

*Actually that may be caused by the following missing from the imports in the original answer:

import java.util.List;

I've updated the original answer now, adding this.

virendra_raval
Explorer
0 Kudos

Hi Kevin,

Both the above suggestions still give the same error message.

Hi Virendra,

When an iflow is fired there is a Camel message object created and this is what is passed through the iflow.

There are Headers values, Exchange Property values and a Body of the message object.

You can pull the Header data and Exchange Property data from a Header value into the Body using a content modifier.

In the Body tab of the Content Modifier, you can put in for example;

Header "orderNo" is ${header.orderNo}

Property "msgOut" is ${property.msgOut}

And you pull them into the Body that way.

.

1. "We think that the solution involves something like this: ${header.filter}"

So yes as long as there actually is a Header called "filter" in the message object then ${header.filter} can be used to access that.

.

2. "But we don’t know what ${header} property to use and we can’t find any documentation that clearly identifies the available ${header} properties."

You can use a Groovy Script step to transfer all the Headers and Properties to the Body, where you can then see them, if you wish. Use the following script I've created for you to amomplish this:

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.util.List;

def Message processData(Message message) 
{

// get the body as a string (no type casting needed as groovy is dynamic language)
def body_as_string = message.getBody();

// get the headers from the Message object
def message_headers = message.getHeaders();

// get the properties from the Message object
def message_properties = message.getProperties();

// create a new string to display in the Body
def new_body_string =
"""
This message was created using the Apache Groovy Language.

All Headers: ${message_headers}

All Properties: ${message_properties}
"""

// set the Body of the Message object with the new string we created now
message.setBody(new_body_string);

return message;
}

.

You can also log the body to the MPL as an attachment, which you can then look at.

How to do that is explained here: https://blogs.sap.com/2017/01/09/hci-payload-logging-sorted-using-groovy-script/

saranya_baskaran2
Participant
0 Kudos

Hi Virendra,

Please refer to the blog https://blogs.sap.com/2019/08/12/odata-service-in-cpi-for-beginners/#Query

It explains how each of the OData query options can be extracted and used as message header in the Integration flow.

BR
Saranya

0 Kudos

Hello Anil,

Can you explain how you are using an HTTP *sender* channel to obtain the incoming OData query URL? In our use case, we have an HTTP *receiver* channel that is receiving an incoming OData request with the OData query parameters. It doesn't make sense to us that a *sender* is part of the solution.

--- Andrew

virendra_raval
Explorer
0 Kudos

Thanks Kevin for the response. In order to understand the content of header, properties and payload during the execution of iFlow, we are trying to get logs as attachment as mentioned as the above link and able to generate the attachment. However, when we try to open it, it fails with the below message. Any idea what could be wrong here?

"Request for log attachments failed with error: Invalid server response: Couldn't parse message. Status Code: 500 Message: <?xml version="1.0" ?><error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><code>Internal Server Error</code><message xml:lang="en">while trying to invoke the method java.io.InputStream.read(byte[]) of a null object loaded from local variable 'is'</message></error>"

0 Kudos

Hi Virendra,

You are having trouble logging the payload?

Try the following code in a groovy script step (make sure it's not a javascript step):

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;

def Message processData(Message message) 
{
    def body = message.getBody(java.lang.String) as String;
    def messageLog = messageLogFactory.getMessageLog(message);
    if(messageLog != null)
{
        messageLog.addAttachmentAsString("ResponsePayload:", body, "text/plain");
     }
    return message;
}