使用 Apache Camel 2.25.0 将 JSON 转换为 CSV 时获取 com.thoughtworks.xstream.mapper.CannotResolveClassException
Getting com.thoughtworks.xstream.mapper.CannotResolveClassException while converting JSON to CSV using Apache Camel 2.25.0
我正在使用 Spring Boot 2.6.2、Apache Camel 2.25.0、JDK 1.8.
将 JSON 转换为 CSV
下面是我为此使用的 Camel Route 代码片段:
@Override
public void configure() throws Exception {
// Receive from JSON file
from("file:files/input")
.log("Received file - ${body}")
// transform JSON to CSV format
.unmarshal().json()
.marshal().csv()
// Write to output file
.log("Writing file - ${body}")
.to("file:files/output");
}
源代码:https://github.com/DebeshNayak/camel-json-to-csv
此应用程序构建成功,但在运行时出现以下错误:
2022-01-04 11:10:47.813 INFO 14788 --- [e://files/input] route1 : Received file - {
"fname": "debesh",
"lname": "nayak"
}
2022-01-04 11:10:47.862 ERROR 14788 --- [e://files/input] o.a.camel.processor.DefaultErrorHandler : Failed delivery for (MessageId: ID-Debesh-Lenovo-i5-1641274844914-0-2 on ExchangeId: ID-Debesh-Lenovo-i5-1641274844914-0-1). Exhausted after delivery attempt: 1 caught: com.thoughtworks.xstream.mapper.CannotResolveClassException: fname
Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId ProcessorId Processor Elapsed (ms)
[route1 ] [route1 ] [file://files/input ] [ 60]
[route1 ] [log1 ] [log ] [ 20]
[route1 ] [unmarshal1 ] [unmarshal[org.apache.camel.model.dataformat.JsonDataFormat@5bb0a7b2] ] [ 28]
Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
com.thoughtworks.xstream.mapper.CannotResolveClassException: fname
at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:81) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:71) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:47) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.core.util.HierarchicalStreams.readClassType(HierarchicalStreams.java:29) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:133) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1487) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1455) ~[xstream-1.4.11.1.jar:1.4.11.1]
at org.apache.camel.dataformat.xstream.AbstractXStreamWrapper.unmarshal(AbstractXStreamWrapper.java:374) ~[camel-xstream-2.25.0.jar:2.25.0]
at org.apache.camel.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:69) ~[camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548) ~[camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:454) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:223) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:187) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:174) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:101) [camel-core-2.25.0.jar:2.25.0]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_312]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_312]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_312]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_312]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_312]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_312]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_312]
在我的项目中,我在 pom.xml:
中使用下面的 Maven 依赖项
<properties>
<java.version>1.8</java.version>
<camel.version>2.25.0</camel.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-stream-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-xstream</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-csv</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
但是在使用 Apache Camel 3.4.2 时,它工作正常。
Camel 支持几个不同的 JSON 库,恰好 Camel 3 将其 default JSON 库从 XStream 给 Jackson,这可能就是代码在这里不起作用的原因。 (有关更改的信息,请参阅 CAMEL-5836)。每当您单独使用 .json()
关键字时,都会使用默认库。
所以如果你想在 Camel 2.x 中使用这段代码,或者以任何方式自定义 JSON marshalling/unmarshalling,你可以先显式实例化 Jackson,然后参考它在路线中,例如:
JacksonDataFormat json = new JacksonDataFormat();
// You can also set any Jackson options here
from("file:files/input")
.log("Received file - ${body}")
// transform JSON to CSV format, referring to the "json" object above
.unmarshal(json)
.marshal().csv()
// Write to output file
.log("Writing file - ${body}")
.to("file:files/output");
}
使用 Jackson 比 XStream 简单得多,因为它可以解组为简单的 Java 对象,如 Map,无需太多配置。
我正在使用 Spring Boot 2.6.2、Apache Camel 2.25.0、JDK 1.8.
将 JSON 转换为 CSV下面是我为此使用的 Camel Route 代码片段:
@Override
public void configure() throws Exception {
// Receive from JSON file
from("file:files/input")
.log("Received file - ${body}")
// transform JSON to CSV format
.unmarshal().json()
.marshal().csv()
// Write to output file
.log("Writing file - ${body}")
.to("file:files/output");
}
源代码:https://github.com/DebeshNayak/camel-json-to-csv
此应用程序构建成功,但在运行时出现以下错误:
2022-01-04 11:10:47.813 INFO 14788 --- [e://files/input] route1 : Received file - {
"fname": "debesh",
"lname": "nayak"
}
2022-01-04 11:10:47.862 ERROR 14788 --- [e://files/input] o.a.camel.processor.DefaultErrorHandler : Failed delivery for (MessageId: ID-Debesh-Lenovo-i5-1641274844914-0-2 on ExchangeId: ID-Debesh-Lenovo-i5-1641274844914-0-1). Exhausted after delivery attempt: 1 caught: com.thoughtworks.xstream.mapper.CannotResolveClassException: fname
Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId ProcessorId Processor Elapsed (ms)
[route1 ] [route1 ] [file://files/input ] [ 60]
[route1 ] [log1 ] [log ] [ 20]
[route1 ] [unmarshal1 ] [unmarshal[org.apache.camel.model.dataformat.JsonDataFormat@5bb0a7b2] ] [ 28]
Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
com.thoughtworks.xstream.mapper.CannotResolveClassException: fname
at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:81) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:71) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:47) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.core.util.HierarchicalStreams.readClassType(HierarchicalStreams.java:29) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:133) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1487) ~[xstream-1.4.11.1.jar:1.4.11.1]
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1455) ~[xstream-1.4.11.1.jar:1.4.11.1]
at org.apache.camel.dataformat.xstream.AbstractXStreamWrapper.unmarshal(AbstractXStreamWrapper.java:374) ~[camel-xstream-2.25.0.jar:2.25.0]
at org.apache.camel.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:69) ~[camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548) ~[camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:454) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:223) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:187) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:174) [camel-core-2.25.0.jar:2.25.0]
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:101) [camel-core-2.25.0.jar:2.25.0]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_312]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_312]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_312]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_312]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_312]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_312]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_312]
在我的项目中,我在 pom.xml:
中使用下面的 Maven 依赖项<properties>
<java.version>1.8</java.version>
<camel.version>2.25.0</camel.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-stream-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-xstream</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-csv</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
但是在使用 Apache Camel 3.4.2 时,它工作正常。
Camel 支持几个不同的 JSON 库,恰好 Camel 3 将其 default JSON 库从 XStream 给 Jackson,这可能就是代码在这里不起作用的原因。 (有关更改的信息,请参阅 CAMEL-5836)。每当您单独使用 .json()
关键字时,都会使用默认库。
所以如果你想在 Camel 2.x 中使用这段代码,或者以任何方式自定义 JSON marshalling/unmarshalling,你可以先显式实例化 Jackson,然后参考它在路线中,例如:
JacksonDataFormat json = new JacksonDataFormat();
// You can also set any Jackson options here
from("file:files/input")
.log("Received file - ${body}")
// transform JSON to CSV format, referring to the "json" object above
.unmarshal(json)
.marshal().csv()
// Write to output file
.log("Writing file - ${body}")
.to("file:files/output");
}
使用 Jackson 比 XStream 简单得多,因为它可以解组为简单的 Java 对象,如 Map,无需太多配置。