I have a springboot application with apache camel. In it I have a camel-context. I am trying to send json through curl with a key pair value and processing it through a route.
Sending the data:
curl --header "Content-Type: application/json" -X POST -d '{"msgId=EB2C7265-EF68-4F8F-A709-BEE2C52E842B", "ticket":"ERR001"}' http://lcalhost:8888/api/erroradmin
Camel-context.xml:
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext xmlns="http://camel.apache.org/schema/spring" useMDCLogging="true">
<properties>
<property key="CamelLogEipName" value="ThisLogger"/>
</properties>
<dataFormats>
<!-- here we define a Json data format with the id jack and that it should use the TestPojo as the class type when
doing unmarshal. The unmarshalTypeName is optional, if not provided Camel will use a Map as the type -->
<json id="jack" library="Jackson" unmarshalTypeName="java.util.HashMap"/>
</dataFormats>
<restConfiguration component="jetty" port="8888" bindingMode="json">
<dataFormatProperty key="prettyPrint" value="true"/>
</restConfiguration>
<rest path="/api/erroradmin">
<get uri="{id}">
<to uri="direct:processErrorAdminGet"/>
</get>
<post>
<to uri="direct:processErrorAdminPost"/>
</post>
</rest>
<route id="processErrorAdminPost">
<from uri="direct:processErrorAdminPost"/>
<log message="Route(processErrorAdminPost): ${body}"/>
<unmarshal>
<custom ref="jack"/>
</unmarshal>
<log message="Route(processErrorAdminPost): ${body}"/>
</route>
</camelContext>
</beans>
I am getting the following Stacktrace:
org.apache.camel.InvalidPayloadException: No body available of type: java.io.InputStream but has value: {msgId=D507B9EE-176D-4F3C-88E7-9E36CC2B9731, ticket=ERR001} of type: java.util.LinkedHashMap on: HttpMessage@0x28c1a31a. Caused by: No type converter available to convert from type: java.util.LinkedHashMap to the required type: java.io.InputStream with value {msgId=D507B9EE-176D-4F3C-88E7-9E36CC2B9731, ticket=ERR001}. Exchange[09395660-c947-47f1-b00f-d0d3030a39d1]. Caused by: [org.apache.camel.NoTypeConversionAvailableException - No type converter available to convert from type: java.util.LinkedHashMap to the required type: java.io.InputStream with value {msgId=D507B9EE-176D-4F3C-88E7-9E36CC2B9731, ticket=ERR001}]
After searching and reading for a while, I have found the solution.
The way to do this is by using JsonPath. Now in Java DSL there are many examples, but in XML DSL, there is not much. I finally found a working example.
My camel context looks now like this:
<camelContext xmlns="http://camel.apache.org/schema/spring" useMDCLogging="true" streamCache="true">
<properties>
<property key="CamelLogEipName" value="SomeLogger"/>
</properties>
<dataFormats>
<json id="json" library="Jackson"/>
</dataFormats>
<restConfiguration component="jetty" port="9090" >
<dataFormatProperty key="prettyPrint" value="true"/>
</restConfiguration>
<rest path="/api/erroradmin">
<post>
<to uri="direct:error" />
</post>
</rest>
<route id="error">
<from uri="direct:error"/>
<log message="Route(error): ${body}"/>
<setHeader headerName="errMessageId">
<jsonpath suppressExceptions="true">$[0].msgId</jsonpath>
</setHeader>
<setHeader headerName="errTicket">
<jsonpath suppressExceptions="true">$[0].ticket</jsonpath>
</setHeader>
<setHeader headerName="errHandled">
<jsonpath suppressExceptions="true">$[0].handled</jsonpath>
</setHeader>
<log message="Route(error): Header name: errMessageId -> ${header[errMessageId]}"/>
<log message="Route(error): Header name: errTicket -> ${header[errTicket]}"/>
<log message="Route(error): Header name: errHandled -> ${header[errHandled]}"/>
</route>
</camelContext>
When accessing the key of the corresponding node I get the value in my newly set header.
The JSON is sent in like this: So you send in:
curl -XPOST http://localhost:9090/api/erroradmin -d '[{"var1": 10,"var2": 20}]' --header "Content-Type: application/json"
The dependencies I am using:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jsonpath</artifactId>
<version>${camel.version}</version>
</dependency>
</dependencies>
Hope this benefits someone in the future!
EDIT: Make sure to use camel 2.25.0 and higher. Apparently when using camel-json 2.24.1 along with same core version, the camel-json will download an outdated dependency called json-smart, which misses some classes for JsonPath to work correctly.