自定义Apache Camel数据格式的Spring配置

时间:2012-07-31 21:01:07

标签: spring apache-camel dataformat

我正在使用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&amp;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)并未修复错误。

我仍然想知道为什么我收到此错误,因为我的控制台和日志文件中的大块红色错误并不是很吸引人。

再次感谢。

3 个答案:

答案 0 :(得分:2)

事实证明这是一个非常简单的解决方案(我承认应该很容易看到)。实际上有两种方法可以解决这个问题,其中一种方法只使用spring,其中一种需要额外的java类。

解决方案1 ​​

创建一个扩展DataFormatDefinition的新类,该类具有与自定义DataFormat相同的属性。重写configureDataFormat()方法以设置基础DataFormat的所有属性。添加构造函数以将基础DataFormat设置为CustomDataFormat的实例。现在,您应该能够在春季创建DataFormatDefinition的实例,并在编组或unmarshaling时引用它。

解决方案2(快速和肮脏)

在spring中,创建一个新的DataFormatDefinition bean并将其dataFormat属性设置为对DataFormat spring bean的引用。现在,您应该能够在DataFormatDefinitionmarshaling时引用您的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&amp;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转换作为模板来解决。