3

我正在使用 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) 并不能修复错误。

我仍然想知道为什么我会收到这个错误,因为我的控制台和日志文件中的大块难看的红色错误并不完全吸引人。

再次感谢。

4

3 回答 3

2

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

解决方案 1

创建一个新的扩展类,DataFormatDefinition它与您的 custom 具有相同的属性DataFormat。覆盖该configureDataFormat()方法以设置底层的所有属性DataFormat。添加构造函数以将底层设置DataFormatCustomDataFormat. 现在您应该能够DataFormatDefinition在 spring 中创建一个实例并在编组或unmarshaling.

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

在 spring 中,创建一个新DataFormatDefinitionbean 并将其dataFormat属性设置为对DataFormatspring bean 的引用。现在您应该能够在或DataFormatDefinition时引用您的 bean 。marshalingunmarshaling

于 2012-08-14T18:56:04.563 回答
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 archetype 168 创建了一个新的 camel 2.9.2 项目:remote -> org.apache.camel.archetypes:camel-archetype-spring(创建一个新的 Camel 项目并添加了 Spring DSL 支持。)。这仅包括 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 文件将数据格式弄乱了吗?

更新2

好的,我想我知道它是什么:

http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/model/dataformat/CustomDataFormat.html Camel 已经有一个类命名为您的数据格式。您应该尝试将其重命名为其他名称。CustomDataFormat 扩展了您的错误中提到的 org.apache.camel.model.DataFormatDefinition。Java 应该处理这个问题,因为它是两个不同的命名空间,但是在您的项目设置中可能存在一些导致此冲突的问题。尝试重命名数据格式,看看是否能解决问题。

于 2012-07-31T22:45:49.890 回答
0

我也面临与骆驼 2.10.0 相同的问题。如果您为 ref 提供 org.apache.camel.model.DataFormatDefinition 类型的实例,一切正常!我可以看到两个用于 xmljson 转换的类 --> XmlJsonDataFormat 实现了 DataFormat 和 DataFormatDefinition。

我解决了我也面临的同样问题。实现了一个扩展 DataFormatDefintion 的类 - 在它的 configureDataFormat 方法中为扩展 DataFormat 的类设置可注入属性(在您的情况下,这是 CustomDataFormat)。我使用XmlJson转换作为模板来解决。

于 2012-08-13T02:14:12.367 回答