我正在使用Apache Camel 2.9.2和Spring 3.0.6.RELEASE。我正在尝试使用自定义DataFormat来编组和解组Camel消息。我想使用Spring将我的自定义DataFormat配置到我的一个路由中。
Apache Camel的文档说明为了将自定义数据格式连接到Spring中的路由,我只需要将自定义DataFormat声明为bean并在Spring路径中引用它,如下所示:
<marshal>
<custom ref="myCustomDataFormat"/>
</marshal>
http://camel.apache.org/custom-dataformat.html
所以我有以下设置:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<bean id="myCustomDataFormat" class="com.test.CustomDataFormat"/>
<!-- Camel Context -->
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:C:/test?initialDelay=4000&delay=1000"/>
<marshal>
<custom ref="myCustomDataFormat"/>
</marshal>
<to uri="file:C:/test2"/>
</route>
</camelContext>
</beans>
但是当我尝试启动Camel时,我收到以下令人讨厌的错误:
org.springframework.beans.ConversionNotSupportedException:无法将'com.test.CustomDataFormat'类型的值转换为必需类型'org.apache.camel.model.DataFormatDefinition';嵌套异常是java.lang.IllegalStateException:无法将[com.test.CustomDataFormat]类型的值转换为必需类型[org.apache.camel.model.DataFormatDefinition]:找不到匹配的编辑器或转换策略
我的数据格式定义如下:
package com.test;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.camel.Exchange;
import org.apache.camel.spi.DataFormat;
public class CustomDataFormat implements DataFormat {
/* (non-Javadoc)
* @see org.apache.camel.spi.DataFormat#marshal(org.apache.camel.Exchange, java.lang.Object, java.io.OutputStream)
*/
@Override
public void marshal(Exchange exchange, Object graph, OutputStream stream)
throws Exception {
System.out.println("Marshal");
byte[] bytes = exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class, graph);
stream.write(bytes);
}
/* (non-Javadoc)
* @see org.apache.camel.spi.DataFormat#unmarshal(org.apache.camel.Exchange, java.io.InputStream)
*/
@Override
public Object unmarshal(Exchange exchange, InputStream stream)
throws Exception {
System.out.println("Unmarshal");
byte[] bytes = exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class, stream);
return bytes;
}
}
我知道我的CustomDataFormat实现是正确的,因为我在Java中创建了以下测试路径并且它完美无缺地运行
package com.test;
import org.apache.camel.spring.SpringRouteBuilder;
public class TestFormatRoute extends SpringRouteBuilder {
/* (non-Javadoc)
* @see org.apache.camel.builder.RouteBuilder#configure()
*/
@Override
public void configure() throws Exception {
from("file:C:/test?initialDelay=4000&delay=1000").unmarshal(new CustomDataFormat()).to("file:C:/test2");
}
}
我错过了什么?
由于
更新
在收到此错误后让Camel完全启动后,我发现我的怀疑我的自定义数据格式确实在我创建的路径中起作用。我不确定哪个进程试图解析我的自定义数据格式并失败,但显然不是解析数据格式进入我的路由的过程。
这解决了数据格式的功能要求,但它没有解释我收到此错误的原因。
我还确认这不是导致问题的数据格式(CustomDataFormat)的名称。将我的DataFormat重命名为唯一名称(MerlinDataFormat)并未修复错误。
我仍然想知道为什么我收到此错误,因为我的控制台和日志文件中的大块红色错误并不是很吸引人。
再次感谢。
答案 0 :(得分:2)
事实证明这是一个非常简单的解决方案(我承认应该很容易看到)。实际上有两种方法可以解决这个问题,其中一种方法只使用spring,其中一种需要额外的java类。
解决方案1
创建一个扩展DataFormatDefinition
的新类,该类具有与自定义DataFormat
相同的属性。重写configureDataFormat()
方法以设置基础DataFormat
的所有属性。添加构造函数以将基础DataFormat
设置为CustomDataFormat
的实例。现在,您应该能够在春季创建DataFormatDefinition
的实例,并在编组或unmarshaling
时引用它。
解决方案2(快速和肮脏)
在spring中,创建一个新的DataFormatDefinition
bean并将其dataFormat
属性设置为对DataFormat
spring bean的引用。现在,您应该能够在DataFormatDefinition
或marshaling
时引用您的unmarshaling
bean。
答案 1 :(得分:0)
不确定你的例子有什么问题,看起来很好。你可以发布数据格式的代码吗?您是否正确实现了org.apache.camel.spi.DataFormat?
我刚用Camel 2.9.2设置了这个例子,它就像一个魅力。自定义数据格式是Camel文档/源代码中的格式。
<bean id="mySweetDf" class="com.example.MySweetDf"/>
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:C:/temp/test?initialDelay=4000&delay=1000"/>
<marshal>
<custom ref="mySweetDf"/>
</marshal>
<convertBodyTo type="java.lang.String"/>
<to uri="file:C:/temp/test2"/>
</route>
</camelContext>
数据格式java文件:
package com.example;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.camel.Exchange;
import org.apache.camel.spi.DataFormat;
public class MySweetDf implements DataFormat {
public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception {
byte[] bytes = exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class, graph);
String body = reverseBytes(bytes);
stream.write(body.getBytes());
}
public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
byte[] bytes = exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class, stream);
String body = reverseBytes(bytes);
return body;
}
private String reverseBytes(byte[] data) {
StringBuilder sb = new StringBuilder(data.length);
for (int i = data.length - 1; i >= 0; i--) {
char ch = (char) data[i];
sb.append(ch);
}
return sb.toString();
}
}
<强>更新强>
试过你的代码。似乎也可以工作。通过mvn原型168创建了一个新的骆驼2.9.2项目:远程 - &gt; org.apache.camel.archetypes:camel-archetype-spring(创建一个添加了Spring DSL支持的新Camel项目。)。这只包括camel-core和camel-spring依赖,没有别的。
然后用你的xml替换了camel-context.xml,并在java目录中添加了你的数据格式代码。使用“mvn camel:run”运行复制文件并在日志中打印“marshal”。
[pache.camel.spring.Main.main()] SpringCamelContext INFO Route: route1 started and consuming from: Endpoint[file://C:/test?delay=1000&initialDelay=4000]
[pache.camel.spring.Main.main()] SpringCamelContext INFO Total 1 routes, of which 1 is started.
[pache.camel.spring.Main.main()] SpringCamelContext INFO Apache Camel 2.9.2 (CamelContext: camel-1) started in 0.808 seconds
Marshal
您确定所有依赖项都已正确设置,而不是某些.jar文件会混淆数据格式吗?
<强> UPDATE2 强>
好的,我想我知道它是什么:
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/model/dataformat/CustomDataFormat.html Camel已经有一个名为数据格式的类。您应该尝试将其重命名为其他内容。 CustomDataFormat扩展了错误中引用的org.apache.camel.model.DataFormatDefinition。 Java应该处理这个问题,因为它是两个不同的命名空间,但是在项目设置中可能存在导致此冲突的问题。尝试重命名数据格式,看看是否能解决问题。
答案 2 :(得分:0)
我也遇到了与camel 2.10.0相同的问题。如果你为ref提供一个类型为org.apache.camel.model.DataFormatDefinition的实例,一切正常!!我可以看到xmljson转换的两个类 - &gt; XmlJsonDataFormat实现了DataFormat和DataFormatDefinition。
我解决了同样面临的问题。 实现了一个扩展DataFormatDefintion的类 - 在其configureDataFormat方法中为扩展DataFormat的类设置了可注入属性(在您的情况下,这是CustomDataFormat)。 我使用XmlJson转换作为模板来解决。