0

I'm trying to parse part of a message to a pojo so i can process it in java. The message contains json, but i only need a part of it, so i tried to use jsonpath to pick the part of the json i need, but then i can't unmarshal, i also found a method to create the pojo directly from the jsonpath, but that returns null.

from(...)
.transform()
.jsonpath("@.data", false, POJO.class)
.process(...)
.end()

this leaves my POJO null.

from(...)
.transform.jsonpath("@.data")
.unmarshal().json(JsonLibrary.Jackson, POJO.class)
.process(...)
.end()

This throws an exception:

Error processing exchange. Exchange[ID-5CD9519Z86-1594305984947-0-330]. Caused by: [org.apache.camel.InvalidPayloadException - No body available of type: java.io.InputStream but has value: {...}]
    at org.apache.camel.support.MessageSupport.getMandatoryBody(MessageSupport.java:118)
    at org.apache.camel.support.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:58)
    at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:395)
    at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148)
    at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:60)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:147)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:286)
    at org.apache.camel.impl.engine.DefaultAsyncProcessorAwaitManager.process(DefaultAsyncProcessorAwaitManager.java:83)
    at org.apache.camel.support.AsyncProcessorSupport.process(AsyncProcessorSupport.java:40)
    at org.apache.camel.component.rabbitmq.RabbitConsumer.doHandleDelivery(RabbitConsumer.java:107)
    at org.apache.camel.component.rabbitmq.RabbitConsumer.handleDelivery(RabbitConsumer.java:82)
    at com.rabbitmq.client.impl.ConsumerDispatcher$5.run(ConsumerDispatcher.java:149)
    at com.rabbitmq.client.impl.ConsumerWorkService$WorkPoolRunnable.run(ConsumerWorkService.java:104)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:830)
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 {...}
    at org.apache.camel.impl.converter.CoreTypeConverterRegistry.mandatoryConvertTo(CoreTypeConverterRegistry.java:216)
    at org.apache.camel.support.MessageSupport.getMandatoryBody(MessageSupport.java:116)
    ... 15 common frames omitted

What would be the correct way to handle this.

Thanks in advance,

Bart Laeremans

Bart
  • 61
  • 6
  • I'll suggest to use ObjectMapper, like in the example here: https://stackoverflow.com/questions/51371785/how-do-i-parse-this-json-response-into-pojo – Luca Mattia Ferrari Dec 14 '20 at 15:44

1 Answers1

0

In contrast to xpath which produces String, jsonpath library produces LinkedHashMap. Thus you're trying to unmarshal LinkedHashMap and not String.

e.g. original json: {"books":{"book": {"name": "Some Book"}}} expected json: {"name": "Some Book"} jsonpath expression: "$.books.book"

One would expect to get {"name": "Some Book"} so unmarshaller would produce instance of BookDto. But its not the case.

You may pass result type into jsonpath so it would produce BookDto instead of LinkedHashMap. So won't need to unmarshal anymore. (Like you already did)

The last one didn't work for me though.

String body = exchange.getMessage().getBody(String.class);
BookDto book = JsonPath.parse(body).read("$.books.book", BookDto.class);

book is null :(

But this is JsonPath library issue and not Camel

David
  • 1
  • I got it to work with jsonpath directly. By providing a custom configuration. Configuration conf = Configuration .builder() .mappingProvider(new JacksonMappingProvider(objectMapper)) .build(); POJO p = JsonPath.using(conf).parse(json).read("$.data", POJO.class);` But how do i provide this configuration with Camel? – Bart Jul 10 '20 at 09:23
  • Thanks for the tip with mapping provider. That works for me as well. I am not sure if camel uses some kind of "jsonpath-default" bean which one could override. As a quick dirty hack i can image that you can create processor where you @autowire Configuration conf and then use it like you described. It won't be in the routebuilder itself but may be still better than nothing? – David Jul 10 '20 at 12:44