在apache camel中如何调用一个api并使用从另一个api获得的参数?

yc0p9oo0  于 2022-11-07  发布在  Apache
关注(0)|答案(1)|浏览(325)

我已经通过apache camel调用了一个REST api,并对其进行了反序列化。我需要调用另一个API,并将从调用前一个api中接收到的数字作为参数。我是通过以下方式完成的-

public Collection<String> nos;

     from("direct:further").tracing()
            .log("body: " + body().toString())
            .setBody().constant(null)
            .setHeader("CamelHttpMethod")
            .simple("GET")
            .setHeader("Authorization")
            .simple("Bearer "+"${header.jwt}")
            .to("https://call/api/that/returns/numbers")
            .choice()
            .when().simple("${header.CamelHttpResponseCode} == 200").unmarshal().json(JsonLibrary.Jackson, Abc.class)
    .process(
                ex->{
                  Quantity quantity = ex.getIn().getBody(Abc.class);
                  List<Variations> variationsList = Arrays.stream(quantity.getResources().getVariations()).toList();
                  nos=variationsList.stream().map(Variations::getNo).collect(
                      Collectors.toList());
     nos.forEach(s -> { //Since nos is a collection of String I would like to iterate through it

          String url="https://call/another/api/with/number"+"?"+s;//the link with the number as the parameter 
                    from("direct:start")   //This is not working. I not able to call the url
                        .setHeader("CamelHttpHeader")
                          .simple("GET")
                          .setHeader("Authorization")
                          .simple("Bearer "+"${header.jwt}")
                          .log("I did call the numbers") //This is also not getting printed
                        .to(url);
    });
     }).log("I am out of the loop" + body())
            .otherwise()
            .log("Error!!!");

我无法用我在调用第一个api时收到的号码调用另一个api。我该怎么做呢?我也试着调用它,就像

from("rest:get:"+url).tracing()
                    .setHeader("CamelHttpHeader")
                    .simple("GET")
                    .setHeader("Authorization")
                    .simple("Bearer "+"${header.jwt}")
                    .log("I did call the numbers").to(url);

但不幸的是,上面的代码在循环内部也不起作用。我在方法定义外部声明了集合nos。我应该如何从存储在nos集合中的数字调用另一个API?我应该在lambda函数外部还是内部调用另一个API?

apeeds0o

apeeds0o1#

与其在处理器内部定义新的路由,不如将数字集合存储到body中,并使用split调用dynamic producer endpointtoDdynamic producer endpoint可以使用简单的语言来构造带有body、header、properties等值的uri。
如果你以后需要收集所有的回答,你可以创建自定义的AggregationStrategy或使用灵活的。

Camel 3.18.2使用单元测试的简单示例

package com.example;

import java.util.ArrayList;

import org.apache.camel.AggregationStrategy;
import org.apache.camel.Exchange;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.AdviceWith;
import org.apache.camel.builder.AggregationStrategies;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.model.dataformat.JsonLibrary;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;

public class NumbersAPITests extends CamelTestSupport {

    @Test
    public void testAPILogic() throws Exception {

        replaceHttpEndpointWithSimpleResponse("requestNumbersFromAPI", 
            "[1,2,3,4,5]");
        replaceHttpEndpointWithSimpleResponse("requestDataWithIdFromAPI", 
            "{ \"id\"=\"${body}\", \"data\":\"some data\" }");
        weaveAddMockendpointAsLast("requestNumbersFromAPI", "result");
        weaveAddMockendpointAsLast("requestDataWithIdFromAPI", "splitResult");

        MockEndpoint mockResultEndpoint = getMockEndpoint("mock:result");
        mockResultEndpoint.expectedMessageCount(1);

        MockEndpoint mockSplitResultEndpoint = getMockEndpoint("mock:splitResult");
        mockSplitResultEndpoint.expectedMessageCount(5);

        startCamelContext();

        template.sendBodyAndHeader("direct:requestNumbersFromAPI", null, "jwt", "not-valid-jwt");

        mockResultEndpoint.assertIsSatisfied();
        mockSplitResultEndpoint.assertIsSatisfied();
    }

    @Override
    protected RoutesBuilder createRouteBuilder() throws Exception {

        return new RouteBuilder(){

            @Override
            public void configure() throws Exception {

                AggregationStrategy aggregationStrategy = AggregationStrategies
                    .flexible()
                    .accumulateInCollection(ArrayList.class);

                from("direct:requestNumbersFromAPI")
                    .routeId("requestNumbersFromAPI")
                    .setBody().constant(null)
                    .setHeader("Authorization")
                    .simple("Bearer "+"${header.jwt}")
                    .to("http://localhost:3001/api/numbers")
                    .unmarshal().json(JsonLibrary.Jackson, Integer[].class)
                    .split(body(), aggregationStrategy)
                        .to("direct:requestDataWithIdFromAPI")
                    .end()
                    .to("log:loggerName?showAll=true")
                ;

                from("direct:requestDataWithIdFromAPI")
                    .routeId("requestDataWithIdFromAPI")
                    .setHeader("Authorization")
                    .simple("Bearer "+"${header.jwt}")
                    .convertBodyTo(String.class)
                    .log("Calling API http://localhost:3001/api/data/${body} with number: ${body}")
                    .toD("http://localhost:3001/api/data/${body}")
                    .convertBodyTo(String.class)
                ;
            }
        };
    }

    @Override
    public boolean isUseAdviceWith() {
        return true;
    }

    private void replaceHttpEndpointWithSimpleResponse(String routeId, String simpleResponse) throws Exception {

        AdviceWith.adviceWith(context(), routeId, a -> {

            a.weaveByToUri("http*")
                .replace()
                .setHeader(Exchange.HTTP_RESPONSE_CODE).constant(200)
                .setBody().simple(simpleResponse);
        });
    }

    private void weaveAddMockendpointAsLast(String routeId, String mockName) throws Exception {

        AdviceWith.adviceWith(context(), routeId, a -> {

            a.weaveAddLast()
                .to("mock:" + mockName);
        });
    }
}

生成的请求在body参数的开头和结尾处具有额外的%22。因此它显示为调用失败状态-例如- call/another/api/with/number/%228767%22=如何避免将%22附加到body参数?Jeet
如果您的数据有不应发送到API的额外引号,您可以在调用toD html端点之前删除它们:

setBody().exchange(ex -> { 
    return ex.getMessage().getBody(String.class)
        .replace("\"", ""); 
})

相关问题