如何使用 apache camel 根据正文内容进行 GET api 调用

How to make GET api call based on content of body using apache camel

我的要求是根据我从平面 file.And 吐出的正文内容进行 GET api 调用,将 api 响应与原始正文聚合并生成 xml.

输入:

0150519821|0000000078|0000004892|US| .   
0150519822|0000000078|0000004896|US| .  
0150519824|0000000078|0000004893|US| .  
0150519826|0000000078|0000004898|US|

如果在输入源中是"US",则以第四位为准。我必须进行 GET api 调用才能获得响应。

示例:

GET: return --> { "iD" : 1,"total" :23,"carrier" : "UPS" }

我必须生成 XML,其中包括 GET api 返回的字段以及输入源。

示例输出:

<?xml version="1.0" encoding="UTF-8"?>

<TEST>
  <NUM>0150519821</NUM>
  <ID>0000000078</ID>
  <TOTAL>23</TOTAL>
  <CARRIER>UPS</CARRIER>
</TEST>

上面给定的 xml 输出确实有来自平面文件的两个字段和 api response.I 使用 apache camel bindy 进行拆分并生成 xml。我必须根据我正在拆分的内容进行 api 调用,并汇总 api 返回的响应并生成输出 xml.

这是我实现的路由逻辑,请帮助我如何进行api调用和聚合。

ConverterRoute.java

 public class ConverterRoute implements RoutesBuilder {

        private Logger logger = LoggerFactory.getLogger(ConverterRoute.class);

        private static final String SOURCE_INPUT_PATH = "file://inbox?fileName=test.txt";

        private static final String SOURCE_OUTPUT_PATH = "file://outbox?fileName=file_$simple{date:now:yyyyMMddHHmmssSSS}.xml";

        BindyBeanConfig bindyBeanConfig = new BindyBeanConfig();

        @Override
        public void addRoutesToCamelContext(CamelContext context) throws Exception {

            context.addRoutes(new RouteBuilder() {
                public void configure() {
                    try {

from(SOURCE_INPUT_PATH)
    .split().tokenize(System.lineSeparator())
        .log("After Split input from file and body is ${body}")
        .choice()
            .when(method(MySplitterBean.class,"splitBody").isEqualTo("IN"))
                .unmarshal(bindyBeanConfig())
                .log("After Unmarshal and body is ${body}")
                .marshal()
                .log("After Marshalling and body is ${body}")
                .to(SOURCE_OUTPUT_PATH)
                .log("Finished Transformation")
            .when(method(MySplitterBean.class,"splitBody").isEqualTo("UK"))
                .unmarshal(bindyBeanConfig())
                .marshal()
                .log("After Marshalling and body is ${body}")
                .to(SOURCE_OUTPUT_PATH)
                .log("Finished Transformation")
            .when(method(MySplitterBean.class,"splitBody").isEqualTo("US"))
                .unmarshal(bindyBeanConfig())
                .log("Before Marshalling and body is ${body}")
                .setHeader(Exchange.HTTP_METHOD,constant("GET"))
                .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
                .to("http://localhost:8081/US")
                .process(exchange -> log.info("The response is: {}", exchange.getIn().getBody()))
                .marshal()
                .log("After Marshalling and body is ${body}")
                .to(SOURCE_OUTPUT_PATH)
                .log("Finished Transformation")
        .end();

                    } catch (Exception e) {
                        logger.info(e.getMessage());
                        e.printStackTrace();
                    }
                }
            });
            context.suspend();
            context.stop();
            }
    }

日志:

 2020-01-03 10:20:29.339  INFO 57630 --- [ - file://inbox] route1                                   : Finished Transformation
    2020-01-03 10:20:29.339  INFO 57630 --- [ - file://inbox] route1                                   : Before making api call <?xml version="1.0" encoding="UTF-8"?>

    <TEST>
      <NUM>0150519821</NUM>
      <ID>0000000078</ID>
    </TEST>
    2020-01-03 10:20:29.459  INFO 57630 --- [ - file://inbox] c.s.l.routes.ConverterRoute     : The response code is: org.apache.camel.converter.stream.CachedOutputStream$WrappedInputStream@1a7ebbd1

我能够生成 XML 而无需从 GET api 调用中获取的新字段 (TOTAL,CARRIER)。我正在获取输出流对象,我想用新的两个字段来丰富 xml,因此 xml 如下所示。

从 GET API 调用添加新的两个字段后的预期输出。

<?xml version="1.0" encoding="UTF-8"?>

<TEST>
  <NUM>0150519821</NUM>
  <ID>0000000078</ID>
  <TOTAL>23</TOTAL>
  <CARRIER>UPS</CARRIER>
</TEST> 

所以如果我没理解错的话,你已经做到了XML

<TEST>
    <NUM>0150519821</NUM>
    <ID>0000000078</ID>
</TEST>

但您需要使用 API 调用中的数据来丰富它才能得到这个

<TEST>
    <NUM>0150519821</NUM>
    <ID>0000000078</ID>
    <TOTAL>23</TOTAL>
    <CARRIER>UPS</CARRIER>
</TEST>

例如,您可以使用此页面上的 Camel Enrich EIP. There is a nice example

在你的情况下你可以

  • 将 API 调用外部化到专用路由
  • 从主路由调用新路由以使用 API 响应
  • 丰富当前消息 body

enrich 中引用的聚合策略实现了如何合并消息体。您可以使用 POJO 作为 aggregationStrategy,请参阅链接示例。

您可以使用聚合中的新数据直接丰富 XML body。或者您可以保留旧消息 body 并将新数据保存为聚合中的消息 headers。然后你可以在一个额外的步骤中丰富 XML body。哪个更适合您的情况。

.when(method(MySplitterBean.class,"splitBody").isEqualTo("US"))
    ...        
    .enrich("direct:getCarrierData", aggregationStrategy)
    ...;

from("direct:getCarrierData")
    .setHeader(Exchange.HTTP_METHOD,constant("GET"))
    .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
    .to("http://localhost:8081/US")