Apache Camel REST DSL - 验证请求有效负载并返回错误响应

时间:2018-02-27 14:23:23

标签: rest error-handling apache-camel dsl

我正在使用“CamelHttpTransportServlet”公开一个休息服务,它接收订单并放在jms队列中。代码在快乐路径上正常工作并返回200响应。 我编写了Processor来验证输入JSON,并根据输入设置http_response_code。

问题是 - 对于无效请求,虽然设置了故障响应代码 - 400,但流程继续到下一个路由并将数据推送到队列,而不是将400响应发送回调用应用程序。

    rest("/ordermanagement")
     .post("/order").to("direct:checkInput");

   from("direct:checkInput")         
     .process(new Processor() { 
         @Override 
         public void process(final Exchange exchange) throws Exception { 

             String requestBody = exchange.getIn().getBody(String.class); 
                 if(requestBody == "" || requestBody== null) {                      
                     exchange.getIn().setBody("{ "error": Bad Request}");
                     exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
                     exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
                 }
         } 
 })
.to("direct:sendToQ");

from("direct:sendToQ")
    .to("jms:queue:orderReceiver")
    .log("Sent to JMS");

有人可以告知这里遗漏的内容并尽可能提供样本吗?

尝试实现onException方法:

   rest("/ordermanagement")
 .post("/order").to("direct:checkInput");


   onException(CustomException.class).handled(true)
 .setHeader(Exchange.HTTP_RESPONSE_CODE, code)
 .setBody(jsonObject);

  from("direct:checkInput")         
 .process(new Processor() { 
     @Override 
     public void process(final Exchange exchange) throws Exception { 

         String requestBody = exchange.getIn().getBody(String.class); 
             if(requestBody == "" || requestBody== null) {                      
                 throw CustomException(code, jsonObject)
             }
     } 
  })
  .to("direct:sendToQ");

  from("direct:sendToQ")
.to("jms:queue:orderReceiver")
.log("Sent to JMS");

但是我无法弄清楚如何将参数 - 代码,jsonObject从处理器传递给onException块。

对此有何帮助?这可行吗?

3 个答案:

答案 0 :(得分:5)

这是一种方法。您可以使用choice

    rest("/ordermanagement")
        .post("/order").to("direct:checkInput");

    from("direct:checkInput")
        .process(exchange -> {
          String requestBody = exchange.getIn().getBody(String.class);
          if(requestBody == null || requestBody.equals("")) {
            exchange.getIn().setBody("{ "error": Bad Request}");
            exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
            exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
          }
        })
        .choice()
        .when(exchange -> {
          Object header = exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE);
          return header != null && header.equals(400);
        })
        .stop()
        .otherwise()
        .to("direct:sendToQ")
        .endChoice();

    from("direct:sendToQ")
        .to("jms:queue:orderReceiver")
        .log("Sent to JMS");

答案 1 :(得分:3)

我使用下面代码示例中的内容:

onException(CustomException.class)
    .handled(true)
    .bean(PrepareErrorResponse.class)
    .log("Error response processed");

rest("/ordermanagement")
    .post("/order")
        .to("direct:checkInput");

from("direct:checkInput")     
    .process((Exchange exchange) -> { 
         String requestBody = exchange.getIn().getBody(String.class); 
         if(requestBody == "" || requestBody== null) {                      
             throw new CustomException(code, jsonObject);
         }
    })
    .to("direct:sendToQ");

from("direct:sendToQ")
    .to("jms:queue:orderReceiver")
    .log("Sent to JMS");

Camel将存储在交换所属性中捕获的任何异常,因此应该通过Exchange.EXCEPTION_CAUGHT属性密钥获取。下面的示例说明了这样的自定义错误消息bean的外观:

public class PrepareErrorResponse {

    @Handler
    public void prepareErrorResponse(Exchange exchange) {
        Throwable cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);

        if (cause instanceof CustomException) {
            CustomException validationEx = (CustomException) cause;
            // ...
        }

        Message msg = exchange.getOut();
        msg.setHeader(Exchange.CONTENT_TYPE, MediaType.APPLICATION_JSON);
        msg.setHeader(Exchange.HTTP_RESPONSE_CODE, 400);

        JsonObject errorMessage = new JsonObject();
        errorMessage.put("error", "Bad Request");
        errorMessage.put("reason", cause.getMessage());
        msg.setBody(errorMessage.toString());
        // we need to do the fault=false below in order to prevent a 
        // HTTP 500 error code from being returned
        msg.setFault(false);
    }
}

Camel提供了几种实际处理异常的方法。这里介绍的方式只是一个例子。但是,建议的代码允许对不同的捕获异常以及其他内容使用自定义重新传递策略。如果错误可以在异常处理程序中得到解决,则路由将在异常发生时进行(即应用了重新传递策略的临时网络问题)。如果错误无法在处理程序中得到修复,则交换将停止。通常,人们会将当前处理的消息发送到DLQ并记录有关错误的内容。

请注意,此示例将假设CustomExceptionunchecked exception,因为处理器将替换为更简单的lambda。如果您不能或不想使用此类异常(或lambda表达式),请将lambda-processor替换为new Processor() { @Override public void process(Exchange exchange) throws Exception { ... } }构造。

答案 2 :(得分:0)

在处理器中将 ROUTE_STOP 属性设置为 true 会阻止进一步的处理并返回响应:

...
exchange.getIn().setBody("{ "error": Bad Request}");
exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);

exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
...