json - Apache-camel:如何将 json 对象(由 curl 发送)处理为 header ?

标签 json apache-camel spring-camel camel-jackson

我有一个带有 apache camel 的 springboot 应用程序。在其中我有一个 Camel 语境。 我正在尝试通过带有 key 对值的 curl 发送 json,并通过路由对其进行处理。

发送数据:

curl --header "Content-Type: application/json" -X POST -d '{"msgId=EB2C7265-EF68-4F8F-A709-BEE2C52E842B", "ticket":"ERR001"}' http://lcalhost:8888/api/erroradmin

Camel 上下文.xml:

<?xml version="1.0" encoding="utf-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd         http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
        <camelContext xmlns="http://camel.apache.org/schema/spring" useMDCLogging="true">
            <properties>
                <property key="CamelLogEipName" value="ThisLogger"/>
            </properties>
            <dataFormats>
                <!-- here we define a Json data format with the id jack and that it should use the TestPojo as the class type when
                     doing unmarshal. The unmarshalTypeName is optional, if not provided Camel will use a Map as the type -->
                <json id="jack" library="Jackson" unmarshalTypeName="java.util.HashMap"/>
            </dataFormats>

            <restConfiguration component="jetty" port="8888" bindingMode="json">
                <dataFormatProperty key="prettyPrint" value="true"/>
            </restConfiguration>

            <rest path="/api/erroradmin">
                <get uri="{id}">
                    <to uri="direct:processErrorAdminGet"/>
                </get>
                <post>
                    <to uri="direct:processErrorAdminPost"/>
                </post>
            </rest>

            <route id="processErrorAdminPost">
                <from uri="direct:processErrorAdminPost"/>
                <log message="Route(processErrorAdminPost): ${body}"/>
                <unmarshal>
                    <custom ref="jack"/>
                </unmarshal>
                <log message="Route(processErrorAdminPost): ${body}"/>

            </route>
        </camelContext>
    </beans>

我得到以下 Stacktrace:

org.apache.camel.InvalidPayloadException: No body available of type: java.io.InputStream but has value: {msgId=D507B9EE-176D-4F3C-88E7-9E36CC2B9731, ticket=ERR001} of type: java.util.LinkedHashMap on: HttpMessage@0x28c1a31a. Caused by: No type converter available to convert from type: java.util.LinkedHashMap to the required type: java.io.InputStream with value {msgId=D507B9EE-176D-4F3C-88E7-9E36CC2B9731, ticket=ERR001}. Exchange[09395660-c947-47f1-b00f-d0d3030a39d1]. 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 {msgId=D507B9EE-176D-4F3C-88E7-9E36CC2B9731, ticket=ERR001}]

最佳答案

欢迎使用 Stackoverflow! 我坚信第 13 行提到的 bindingMode="json" 是这次失败的根本原因。 manual

When using binding you must also configure what POJO type to map to. This is mandatory for incoming messages, and optional for outgoing.

我真的很害怕 XML DSL,但是这里有一个近似等效的 Java 其余 DSL。

@Component
@Slf4j
public class MySpringBootRouter extends RouteBuilder {

    @Override
    public void configure() {

        restConfiguration()
                .component("undertow")
                .host("127.0.0.1")
                .port(9090)
                //This works only when a POJO mapping is possible - Ref: https://camel.apache.org/manual/latest/rest-dsl.html
                //<quote>When using binding you must also configure what POJO type to map to. This is mandatory for incoming messages, and optional for outgoing.</quote>
                //.bindingMode(RestBindingMode.json)
                .dataFormatProperty("prettyPrint", "true");


        rest("/api")
                .post("/erroradmin")
                .to("direct:postError")

                .get("/erroradmin/{id}").to("direct:getError");

        from("direct:getError")
                .process(exchange -> {
                    exchange.getMessage().setBody(("{'messageID':'" + UUID.randomUUID().toString() + "','ticketID':'1234'}"));
                });

        from("direct:postError")
                .unmarshal()
                .json(JsonLibrary.Jackson)
                .process(exchange -> {
                    log.info("Type of incoming body:{}", exchange.getIn().getBody().getClass().getName());
                    log.info("Incoming body:{}", exchange.getIn().getBody());
                }).transform().constant("{'httpResponse:200':'OK'}");
    }

}

启动后,我使用 cURL 发送有效载荷,如下所示

curl -d '{"msgId":"EB2C7265-EF68-4F8F-A709-BEE2C52E842B", "ticket":"ERR001"}' -H "Content-Type: application/json" -X POST http://localh
ost:9090/api/erroradmin

你会在日志中看到类似下面的内容

2020-02-18 11:44:13.032  INFO 2708 --- [  XNIO-1 task-4] o.a.c.community.so.MySpringBootRouter    : Type of incoming body:java.util.LinkedHashMap
2020-02-18 11:44:13.032  INFO 2708 --- [  XNIO-1 task-4] o.a.c.community.so.MySpringBootRouter    : Incoming body:{msgId=EB2C7265-EF68-4F8F-A709-BEE2C52E842B, ticket=ERR001}

哦,顺便说一句,您的原始 JSON 负载格式不正确。 整个Java项目是available here , 如果你想玩的话


编辑:额外的标题处理步骤

        from("direct:postError")
                .unmarshal()
                .json(JsonLibrary.Jackson)
                .process(exchange -> {
                    LinkedHashMap map = exchange.getIn().getBody(LinkedHashMap.class);
                    map.keySet().stream().forEach( item -> exchange.getIn().setHeader(item.toString(),map.get(item)));
                })
//This step is just to print the Headers. Doesnt do anything useful
                .process( exchange -> {
                    log.info(String.valueOf(exchange.getIn().getHeaders()));
                })
                .transform().constant("{'httpResponse:200':'OK'}");

关于json - Apache-camel:如何将 json 对象(由 curl 发送)处理为 header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60264067/

相关文章:

apache-camel - Camel SFTP 文件处理问题

java - SpringBoot Camel ActiveMQ 嵌入式代理意外停止并重新启动

json - package.json 必须是实际的 JSON,而不仅仅是 JavaScript

php - 如何用smarty生成json?

javascript - 如何从 window.fetch() 响应中获取数据?

java - 重启Camel上下文时Http连接池关闭

java - 使用和公开 REST 服务并传递 JSON 正文

java - 连接 @JsonProperty 值 - Java Jackson

apache-camel - Apache Camel MQXAQueueConnectionFactory

jms - Camel 、JMS、CLIENT_ACKNOWLEDGE 模式