I\m sitting outside and enjoying the last sun and summer we have here in Scandinavia. So I might as well take time to write this blog entry which has been on my todo list for a while.
Camel has a built-in expression language called
Simple. It has been around for a very long time. It started out as a "templatish" (
String interpolation) language, which allows you to define dynamic strings, using token placeholders.
For example you could set a mail subject header as follows:
.setHeader("subject", "Your order from ${header.company}")
In Camel 2.0 we added support for operators in the Simple language. This was a good addition, as it allows end users to use Simple languages for predicates. In other words you have a built-in language in camel-core, which you can use in the Camel routes with EIPs that uses predicates.
For example you could route messages depending on the content using the Content Based Router:
.choice()
.when().simple("${header.priority} > 10")
.to("activemq:queue:high")
.when().simple("${header.priority} > 5")
.to("activemq:queue:med")
.otherwise()
.to("activemq:queue:low")
.end()
As the roots of the Simple language was based on its templatish behavior, there parser was implemented using regular expressions. However as people may know, using regular expressions comes with a cost of complexity and being able to read and understand the fairly long patterns. So we have probably reached how far we could go with the Simple language.
Another problem with using regular expression is that, as an end user, you must enter the input correctly. If you had some typos in the input, then the regular expressions was not always capable of detecting those errors, and being able to report this as an error. Instead the predicate would fallback and pass as true. This leads to confusion and frustration by the end users, as they do not understand, why all their messages goes to the first predicate in their content based router etc.
Knowing this, I took the time to work on a new and improved Simple language. To avoid disturbing the existing source code in the trunk. I setup a new project at
github, and
asked people in the community to participate.
Taariq responded and we worked on this project. A reason for using a repository outside the Camel trunk, was that this was an experiment, and we did not knew when we set sail, if this would become useable and better.
The new improved Simple language is based on the principles of a
recursive descent parser, with a grammar, syntax parser, and ast (abstract source tree). We set a goal to not depend on any 3rd party frameworks such as ANTLR or the likes. The Simple language is simple, and do not need to overhead and complexity of ANTRL or Eclipse XText. There is already sufficient
3rd party languages you can use instead such as JavaScript, Groovy, Mvel etc. However maybe in the future we may develop a new Camel language outside camel-core, that uses ANTRL/XText if the community is looking for this kind, and its feasible to implement.
With the new syntax parser we are capable of detecting all syntax errors, and give a precise error report what is the problem. For example if you forgot to use == in the equals operator, and only have =, then you get a error as follows:
org.apache.camel.language.simple.SimpleIllegalSyntaxException:
unexpected character symbol at location 15
${header.high} = true
^
And there is a ^ pointer, which points you to the location of the problem.
This re-architecture of the Simple language, also allows us to add new operators and functions to the language without the implications of the old regular expression approach. The community was asking for being able to increment a counter using the Simple language purely from the XML DSLs. So this is now possible as follows:
<setHeader header="myCounter">
<simple>${header.myCounter}++</simple>
</setHeader>
We have support for unary operators specified on the postfix side of the operator. So we could potential add other operators, if it makes sense.
I have also experimented with ternary operators, so you can do the conditional operator such as:
<setHeader header="bigSpender">
<simple>${header.amount} > 1000 ? true : false</simple>
</setHeader>
Likewise we may add support for the elvis operator (?:) as a shorthand for the conditional operator:
<setHeader header="name">
<simple>${header.username} ?: "Anonymous"</simple>
</setHeader>
Anyway what I wanted to say with this blog entry, is that the Simple language is improved in the upcoming Camel 2.9 release, so it will give you better error details when you have syntax errors, and all your troubles with why the content based router is rouging all messages to the first predicate is solved as well.