java - Camel Spring MVC 集成

标签 java spring spring-mvc apache-camel

我想使用 Spring MVC 和 Camel 集成服务器公开 RESTful 服务。此服务将接受 JSON 作为输入并仅返回 JSON 输出。

主要思想 - 定义一个接受来自某个 URI 的 POST 请求的路由,Camel 将这个请求转发给 Spring Controller ,Spring Controller 返回一些 JSON 响应,Camel 应该处理它并返回给其余客户端。

这里是我定义的路线

<camel:route>
    <camel:from
            uri="restlet:/url1?restletMethod=POST" />
        <camel:setBody>
                <camel:simple>${body}</camel:simple>
        </camel:setBody>
        <camel:setHeader headerName="Content-Type">
            <camel:constant>{application/json}</camel:constant>
        </camel:setHeader>
            <camel:to uri="restlet:{springMVCUrl}?restletMethod=POST" />
</camel:route>

我从 firefox Rest 客户端点击 Url1 并发送我的 JSON,请求来自 Camel 到我的 Spring Controller ,它返回 JSON 字符串。 如果我在 camel 端调试 eclipse 中的代码,它绝对可以正常工作。

但是如果我在没有 Debug模式的情况下运行,它总是返回空主体

是同步问题还是输入输出 channel 问题?

最佳答案

您面临的问题是 ReSTLet 生产者端点的 Async 处理行为。有关 Camel 异步处理的详细信息以及不同组件如何使用的详细信息 here . “来自”部分调用 RestletConsumer路线的“到”部分调用 RestletProducer . 默认情况下,ReSTLet 生产者以 Async 模式 运行,它刚刚通过交换并在完成工作(在您的情况下调用外部服务)时填充 找的零钱。这可以在 RestletProducer 中验证实现 DefaultAsyncProducer

的类
public class RestletProducer extends DefaultAsyncProducer {

.......................................
......................................

 @Override
    public boolean process(final Exchange exchange, final AsyncCallback callback) {
        RestletEndpoint endpoint = (RestletEndpoint) getEndpoint();

        final RestletBinding binding = endpoint.getRestletBinding();
        Request request;
        try {
            String resourceUri = buildUri(endpoint, exchange);
            request = new Request(endpoint.getRestletMethod(), resourceUri);
            binding.populateRestletRequestFromExchange(request, exchange);
        } catch (CamelExchangeException e) {
            // break out in case of exception
            exchange.setException(e);
            callback.done(true);
            return true;
        }

        // process the request asynchronously
        LOG.debug("Sending request: {} for exchangeId: {}", request, exchange.getExchangeId());
        client.handle(request, new Uniform() {
            @Override
            public void handle(Request request, Response response) {
                LOG.debug("Received response: {} for exchangeId: {}", response, exchange.getExchangeId());
                try {
                    if (response != null) {
                        Integer respCode = response.getStatus().getCode();
                        if (respCode > 207 && throwException) {
                            exchange.setException(populateRestletProducerException(exchange, response, respCode));
                        } else {
                            binding.populateExchangeFromRestletResponse(exchange, response);
                        }
                    }
                } catch (Exception e) {
                    exchange.setException(e);
                }
            }
        });

        callback.done(false);
        return false;
    }

调试路由时输出以下信息。请注意它所说的“Exchange 已处理并继续为 exchangeId 异步路由

01:08:03.824   [qtp723059574-46] TRACE org.apache.camel.processor.Pipeline - Processing complete for exchangeId: ID-NB0629-50370-1395170917014-0-2 >>> Exchange[Message: [Body is instance of java.io.InputStream]]
01:08:03.825   [qtp723059574-46] TRACE o.a.c.p.CamelInternalProcessor - Exchange processed and is continued routed asynchronously for exchangeId: ID-NB0629-50370-1395170917014-0-2 -> Exchange[Message: [Body is instance of java.io.InputStream]]
01:08:03.831   [qtp723059574-46] TRACE org.apache.camel.processor.Pipeline - Processing exchangeId: ID-NB0629-50370-1395170917014-0-2 is continued being processed asynchronously
01:08:03.832   [qtp723059574-46] TRACE o.a.c.p.CamelInternalProcessor - **Exchange processed and is continued routed asynchronously for exchangeId**: ID-NB0629-50370-1395170917014-0-2 -> Exchange[Message: [Body is instance of java.io.InputStream]]
01:08:03.834   [qtp723059574-46] DEBUG o.a.c.c.r.DefaultRestletBinding - Populate Restlet response from exchange body: org.restlet.engine.io.UnclosableInputStream@c107903
Mar 19, 2014 1:08:03 AM org.restlet.engine.log.LogFilter afterHandle
INFO: 2014-03-19        01:08:03        0:0:0:0:0:0:0:1 -       0:0:0:0:0:0:0:1 8082    POST    /context/endpoint        -       200     -       66      221     http://localhost:8082   Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36   -
01:08:06.251   [Restlet-1502737852] DEBUG o.a.c.c.restlet.RestletProducer - Received response: HTTP/1.1 - OK (200) - OK for exchangeId: ID-NB0629-50370-1395170917014-0-2
01:08:06.253   [Restlet-1502737852] DEBUG o.a.c.c.r.DefaultRestletBinding - Populate exchange from Restlet response header: org.restlet.virtualHost value: 344880096
01:08:06.254   [Restlet-1502737852] DEBUG o.a.c.c.r.DefaultRestletBinding - Populate exchange from Restlet response header: org.restlet.context value: org.restlet.Context@6675e3e5
01:08:06.254   [Restlet-1502737852] DEBUG o.a.c.c.r.DefaultRestletBinding - Populate exchange from Restlet response header: org.restlet.http.headers value: [[Set-Cookie: JSESSIONID=s5bnkehrfq2d1hd9mc2jz93rf;Path=/finnone-webapp], [Expires: Thu, 01 Jan 1970 00:00:00 GMT], [Content-Type: application/json;charset=UTF-8], [Transfer-Encoding: chunked], [Server: Jetty(8.1.12.v20130726)]]
01:08:06.307   [Restlet-1502737852] DEBUG o.a.c.c.r.DefaultRestletBinding - Populate exchange from Restlet response: { Your expected JSON response comes here}

Camel 文档声明 here出于可伸缩性原因,多个组件使用此异步行为,但可以通过在中使用 synchronous=true 强制它们以同步方式运行 端点配置。然而不幸的是,reSTLet 生产者似乎并不支持这一点,因为我在他们的配置中看不到任何这样的 URI 选项 here . 还可以查看 RestletComponent似乎没有人支持这一点。

另一方面,Apache CXF 组件确实支持同步调用,如 URI 选项列表中所述 here .

关于java - Camel Spring MVC 集成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22476632/

相关文章:

java - 如何直接从上一个 Activity 返回到第一个使用移动后退按钮?

java - 泛型中的类型安全

java - 在 Java 中基于 XPath 创建 XML 节点

java - 分派(dispatch)到 View 时,如何停止使用 Spring 处理程序中的命令对象隐式丰富模型?

java - Eclipse:如何在底部 Pane 中显示“标记”选项卡

java - Spring MVC - 文件上传 - etat HTTP 500 错误消息

java - 如何在spring webapp中创建后台进程?

java - HSQLDB登录认证问题

java - 我们如何将 json 发送到 Controller 并基于 java 中的键进行迭代?

java - Spring REST - 当资源尚不存在时正确的 PUT 功能