Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
MortenWittrock
Active Contributor
100,027

Introduction


Simple is a, well, simple expression language, that ships with the Apache Camel integration framework. SAP Cloud Integration is based on Apache Camel and the Simple expression language is available for use in your integration flows.

The main use of the language in SAP Cloud Integration is to access the contents of the message being processed and its exchange, to add dynamic content to e.g. the message payload and channel configuration, and to construct condition expressions in the Router step. Simple does, however, have a few more tricks up its sleeve.

In this blog post, I will give you an overview of Simple and its features. I will also point out areas where SAP Cloud Integration's version of Simple differs from Apache Camel's.

I'm keeping this blog post up to date with changes to the Simple expression language. The latest update was on November 18th, 2023. At that time, the Apache Camel version in SAP Cloud Integration was 2.24.2-sap-32.

The basics


The most basic Simple expression is the ${ } placeholder containing a built-in variable. This example expression evaluates to the payload of the input message:

${body}

There is an alternative form, $simple{ }, which is partly supported in SAP Cloud Integration. It does not work in Router conditions, however, so stick to using the shorter ${ } form.

In SAP Cloud Integration, the ${ } placeholder can be inserted in e.g. the payload in a Content Modifier step or applied in the Query Editor, adding dynamic values to an OData resource path.

The ${ } placeholder can also be combined with Simple’s operators to produce boolean expressions, which you can then use as conditions in your Router steps.

Built-in variables


Simple’s built-in variables provide you with access to information such as the message payload and header fields. The list below is not exhaustive. For a list of all built-in variables, please refer to the Simple language documentation. However, keep in mind that some of them might not be supported in SAP Cloud Integration.




























































Variable Description
id The ID of the message
exchangeId The ID of the exchange
body The payload of the input message
header.name The contents of the named header
property.name The contents of the named exchange property
date:command:pattern Date and time formatting (more details below)
date-with-timezone:command:timezone:pattern Date and time formatting in a specific time zone (more details below)
random(max) / random(min,max) Generates random integers (more details below)
messageHistory The history of how this exchange was processed
messageHistory(false) Similar to messageHistory, but without the contents of the exchange
camelContext Provides access to the Apache Camel runtime
exception.message The text of the current exception (or null if there's no exception)
sysenv.name The contents of the named environment variable


For more information about the camelContext variable, please see this blog post.

According to the Simple language documentation, property.name is actually deprecated. However, the non-deprecated form, exchangeProperty.name, will cause an error in SAP Cloud Integration if used in a Router condition. This might be fixed in a future update, but for now you should stick to the deprecated form.

It is also possible to access headers and properties as header[name], property[name] and exchangeProperty[name]. These forms do not work in Router conditions, though, so for consistency it makes sense to stick to the header.name and property.name forms.

Nesting placeholders


Simple lets you nest placeholders. This means that if, for instance, the property MyProperty contains the name of a header, the following expression evaluates to the contents of that header:

${header.${property.MyProperty}}

Nesting placeholders in this way is partly supported in SAP Cloud Integration. It works as expected in Router conditions and when creating headers and properties with the Source Type set to Expression (that is, where the value of the header or property is the result of evaluating a Simple expression). However, it does not work in the message body. If you try to add a nested Simple placeholder to the message body in a Content Modifier, the editor will complain about the two closing curly braces. This happens because }} is a symbol reserved for externalized parameters.

Date and time


You can do date formatting in Simple using the date:command:pattern variable. The command part indicates where to get the date to format. To format the current date and time, use the now command. The pattern is a java.text.SimpleDateFormat date and time pattern string, which you might already be familiar with, if you are a Java developer. Here’s an example:

${date:now:dd-MM-yyyy HH:mm}

At the time of writing, this evaluates to 07-03-2021 12:15. The time is, however, 13:15. What gives? Let’s add the pattern letter z, in order to see the time zone:

${date:now:dd-MM-yyyy HH:mm z}

This evaluates to 07-03-2021 12:17 UTC. In other words, the time zone is Coordinated Universal Time (UTC).

To get the time in a specific time zone, use the date-with-timezone variable. Here's an example using my time zone (CET):

${date-with-timezone:now:CET:dd-MM-yyyy HH:mm}

Right now, this evaluates to 07-03-2021 13:18, which is the correct time in Denmark.

To format dates stored in headers and properties, use the header.MyDateHeader and property.MyDateProperty commands, respectively.

Simple in SAP Cloud Integration supports some date arithmetic operations through offsets. In this example, I get the formatted time in CET four and a half hours from now:

${date-with-timezone:now+4h30m:CET:dd-MM-yyyy HH:mm}

The supported offsets are h for hours, m for minutes and s for seconds. You can combine them as in the above example.

To learn more about the SimpleDateFormat pattern strings, please see the class’s API documentation.

Random numbers


Should you need a random number, Simple has you covered by way of the random variable. There are two ways to employ it:

  • random(max)

  • random(min, max)


The first form generates a random integer between 0 (included) and max (excluded), while the second form generates a random integer between min (included) and max (excluded). To generate a random integer between 1 and 10, you would therefore use the following expression:

${random(1, 11)}

Operators


When adding non-XML condition routes to a Router step in your integration flow, you need to construct boolean expressions, i.e. expressions that evaluate to either true or false. The Simple language supports a range of operators, that you can use for this purpose. In the following, I will briefly describe each available operator. For a list of Simple operators supported in SAP Cloud Integration at a given time, please refer to SAP's documentation of the Router step. Please note that currently Simple in Apache Camel supports more operators than Simple in SAP Cloud Integration.

When writing your expressions, please be aware that all literal values must be enclosed in single quotes, regardless of data type. Omitting the quotes will cause an error. If required, the data type of the right-hand value will be converted into the data type of the left-hand value. In other words, this is a valid, numeric comparison, even though it looks like a string comparison at first glance:

${property.MyNumericProperty} > '0'

Comparison operators


The Simple language offers you the familiar comparison operators: =, !=, >, >=, < and <=. For some reason, the equality operator in SAP Cloud Integration’s version of Simple is a single equals sign, even though it’s a double equals sign in Camel’s Simple language documentation.

Please note that string comparison is case sensitive. There’s actually a case insensitive equals operator in the Simple language (=~), but at the moment, it is not supported in SAP Cloud Integration. In order to compare strings without considering case, you can do this instead:

${property.MyStringProperty.toLowerCase()} = 'lower case value'

For more information about calling methods, see Calling methods below.

Logical operators


The two available logical operators are and and or. According to the Simple language documentation, the and and or forms are actually deprecated, but at the time of writing, the alternative forms (&& and ||) are not supported in SAP Cloud Integration. Keep in mind, though, that this might very well change with future SAP Cloud Integration updates.

You can combine multiple and and or operators in the same expression, but you cannot use parentheses for grouping. Consequently, if your boolean expression is long and complex, you are probably better off moving the logic to a Script step instead, for the sake of readability and maintainability.

contains/not contains


The contains operator tests whether a string contains another string, and not contains tests whether it doesn’t contain the other string. Here’s an example:

${property.MyStringProperty} contains 'test'

As was the case with string comparison, this operator is case sensitive. To disregard case, convert to upper or lower case by calling toUpperCase() or toLowerCase(), respectively.

regex/not regex


Regular expressions are supported in the Simple language via the operators regex and not regex. The former tests whether a value matches the provided regular expression, and the latter tests whether it doesn’t match. Here’s an example that tests whether a product code is formatted as five lower-case letters followed by three digits:

${property.ProductCode} regex '^[a-z]{5}\d{3}$'

in/not in


The in operator tests whether a given value occurs in a list of values, and the not in operator tests whether it doesn’t occur in the list. Here’s an example:

${property.MyNumericProperty} in '1,2,3,4,5'

Note how the entire list in enclosed in single quotes, and how the elements are separated by commas with no whitespace around them. The data type of the list elements will automatically be converted into the data type of the left-hand side value.

When evaluating strings, keep in mind that the comparison is case sensitive. To disregard case, convert the left-hand side to upper or lower case first:

${property.MyStringProperty.toLowerCase()} in 'abc,def'

Calling methods


As we saw in the above with the toLowerCase() method of Java class String, you can call methods on objects in your expressions using the familiar dot notation.

Simple provides this functionality by supporting a subset of another Apache language called OGNL. Here’s an example:

${property.MyStringProperty.substring(0,4)} = 'test'

Here, the substring method of class String is called, and two integer parameters are passed to the method.

For straightforward method calls with scalar parameters, this works well. However, if your method invocation is more complicated, e.g. if it requires creating and passing objects to the method, moving it to a Script step is the way to go.

Also, there is a special case you need to be aware of: Examples will show method calls without parentheses, and if you are calling a method that doesn’t take any parameters, you don’t need them, unless the method is overloaded. When calling an overloaded method that takes no parameters, you need to append a pair of empty parentheses. Otherwise the call will be ambiguous, and you will end up with a runtime error.

Support for arrays, Lists and Maps


In a Simple expression, you can directly access the elements of arrays and Lists using their index:

${property.MyList[0]}

Simple supports a special keyword called last, which you can use to return the last element of a List or an array:

${property.MyArray[last]}

You can even subtract numbers from last. You can get the second to last element like this:

${property.MyList[last-1]}

Maps are also supported directly in Simple expressions. You can retrieve a value from a Map like this:

${property.MyMap[key]}

Notice how I didn't have to put the key in quotes. This works even if the key has spaces in it.

Using Simple expressions in Groovy


In the above, I've talked about various integration flow steps that support Simple expressions. There is one more option, though: Using Simple expressions in your Groovy scripts. Apache Camel enables this via the org.apache.camel.builder.SimpleBuilder class.

How to accomplish this is described in detail in this blog post by Eng Swee Yeoh. The approach works in SAP Cloud Integration, but be aware that it is not officially documented by SAP.
25 Comments
apu_das2
Active Contributor
Great job Morten. Nice and helpful blog.
MortenWittrock
Active Contributor
Thank you to the Apache Camel guys for the link from the Camel articles page 🙂
nitindeshpande
Active Contributor
Simple has been explained in a very simple way 😉 Thanks Morten for sharing it..
Very well explained with simplicity Morten. Thanks...
former_member230091
Participant
Hi Morten,

I checked this below Date now function and its working.

${date:now:dd-MM-yyyy HH:mm z}

But by default I am getting time in UTC format. My requirement is to have it in EET or IST.

Can we achieve this timezone conversion here itself by specifying EET or need to go for scripts.?

Kindly help me on this case.

 

Regards,

Deva
MortenWittrock
Active Contributor
0 Kudos
Hi Deva

Sorry about the late reply. It does seem like the timestamp is returned in UTC, so you will probably have to convert in a script, if you need a different time zone.

Regards,

Morten

 
PiotrRadzki
Active Participant
Hi Morten,

thanks for the tips about Camel's Simple expressions. I found it really usefull, fast and efficient.

Especially it make sense while making simple conversion of Exchange Properties like this one  ${property.ExchangeRateDate.replace("-","/")

BR,

Piotr

 
Thanks a lot Morten,

I had been looking for syntax to specify current date and the one mentioned in this blog worked perfectly. Thanks again.

Regards,

Netrey
MortenWittrock
Active Contributor
0 Kudos
No problem - I'm glad you found it useful!

Regards,

Morten

 
0 Kudos
Hi Morten,

I need help again on the date front. My requirement is to get records from successfactors that were created yesterday. I am not sure how do I specify yesterday's date. Could you please help?

Also, do we have any documentation from SAP where I get all the syntax?

Regards,

Netrey
hsonnenahalli
Contributor
0 Kudos
Morten-

Hope all is well. I am using following expression in my iflow to retrive data for current date.

{"day":["between","${date:now:yyyy-MM-dd}”,”${date:now:yyyy-MM-dd}”]}


My understanding is that above expression will provide current date irrespective of the time zone. Using which I can schedule my iflow to run for a specific timezone. What am seeing is that data load stops after 4PM PST which is next day in UTC time zone. Is above expression in UTC, if yes please let me know if there is any expression to get the date in PST.

 

Regards

 

HS
MortenWittrock
Active Contributor
0 Kudos
Hi Netrey

I don't believe that's possible without scripting.

Please post any follow-up questions in the Q&A section, where other community members will see and possibly respond to them.

Regards,

Morten
MortenWittrock
Active Contributor
0 Kudos
Hi Hari

I believe the timestamp is returned in UTC. To change this, you need scripting.

Please post any follow-up questions in the Q&A section, where other community members will see and possibly respond to them.

Regards,

Morten

 
hsonnenahalli
Contributor
0 Kudos
Will do. Thanks for the confirmation.

 

Regards

 

HS
PiotrRadzki
Active Participant
0 Kudos

Hi Deva,

try to follow these hints for specific local time zone:

https://blogs.sap.com/2018/02/28/using-local-time-zone-for-target-file-name-on-cloud-platform-integr...

BR, Piotr

john_knight00
Explorer
0 Kudos
Is there any way you can obtain the user ID that executed the message? If I were to use the integration platform authenticating with IAS or SFSF, is there a way I can get the current user as an input parameter for further API calls?
n_rvsavinashvarma
Participant
0 Kudos
Hi Moten,

 

Hope you are doing good.

 

I have a requirement to read the directory details  dynamically and pass into mapping as a input for one of the filed in CPI.

could you please guide me the camel expression to fetch the folder details dynamically from the source SFTP.

 

Thanks in advance!

 

-Avinash

 

 
saisreenivas
Participant
Hi.
Is there a way to capture Integration Flow name using Simple Expression without using groovy?

 

Thanks,

Sai Sreenivas
MortenWittrock
Active Contributor
Hi Sai

Almost. ${camelId} returns the ID (i.e. not the name) of the iflow.

Regards,

Morten
babruvahana
Contributor

Hi Morten,

Thanks for sharing the very useful blog.

I am sure that I’ll re-visit this post for many times.

Is there anyway expression to convert UNIX date format to normal date format? Or any other way to achieve it?

Regards,

Pavan

MortenWittrock
Active Contributor
0 Kudos
Hi Pavan

That you cannot do in Simple, I'm afraid.

Regards,

Morten
DG
Active Contributor
Hi

It is now possible to perform time additions on the date objects.

You can use ${date:property.CamelCreatedTimestamp+1h}  or ${date:property.CamelCreatedTimestamp+1h}. 

It does require you are on CF where then Camel has been updated.

I wrote about it here.
MortenWittrock
Active Contributor
0 Kudos
Hi Devaraj

Better late than never: You can now do this using the date-with-timezone variable. I've updated the blog post accordingly.

Regards,

Morten
PBhandari1
Explorer
0 Kudos
Hi daniel.graversen,

Is it possible to get current datetime in epoch format using content modifier expressions?

Thanks,

Poushali Bhandari
mathias_rohland
Explorer

Thanks a lot for this very useful blog Morten! This information saved my day and made me speed up my current project.

Regards,
Mathias

Labels in this area