Apache Camel 从 String 消息正文中删除撇号
Apache Camel trims off apostrophes from String message body
import static java.lang.System.out;
import org.apache.camel.ExchangePattern;
import org.apache.camel.Message;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
class RequestReplyMessageSample {
class Replier {
String reply( final String /*Message*/ /*Exchange*/ request ) {
out.println( "\n[ERROR] Expected: 'Re'quest', Actual: " + request
+ " <-- Am I doing somethig wrong, is this a bug or a feature?\n" );
return String.format( "**** Replying to %s ****%n", request/*.getMessage()*/ /*.getBody( String.class )*/ );
}
} // Replier
private static final DefaultCamelContext cc = new DefaultCamelContext();
public static void main( final String... args ) throws Exception {
final Replier replier = new RequestReplyMessageSample().new Replier();
cc.setName( "Request Reply Sample" );
cc.addRoutes( new RouteBuilder() {
@Override
public void configure() {
from( "timer:start?repeatCount=1" )
.setExchangePattern( ExchangePattern.InOut )
.process().message( m -> m.setBody( "'Re'quest'" ) ) // EIP Request
.process().message( m -> print( "Request", m ) )
.log( "Requesting..." )
.log( "Replying..." )
// How to get Message (or Exchange) as argument in here?
.bean( replier, "reply(${body})" ) // EIP Requestor/Replier
.process().message( m -> print( "Reply", m ) ) // EIP Reply (in the body of the Message)
.setId( "Request/Reply" );
}
} );
cc.start();
Thread.sleep( 2000 );
cc.stop();
cc.close();
} // main()
static void print( final String endpoint, final Message m ) {
out.printf( "%s %s: %s%n", endpoint, m, m.getBody() );
} // print()
} // RequestReplyMessageSample
输出
...
Request Message: 'Re'quest'
[ple) thread #1 - timer://start] Request/Reply INFO Requesting...
[ple) thread #1 - timer://start] Request/Reply INFO Replying...
[ERROR] Expected: 'Re'quest', Actual: Re'quest <-- Am I doing somethig wrong, is this a bug or a feature?
Reply Message: **** Replying to Re'quest ****
...
这是一个feature. In this case, the single quotes at the start/end of the expression are interpreted as a string literal start/end。您需要添加另一个单引号让解析器将其视为字符(即 m.setBody("''Re'quest''")
)。
这是因为主体作为显式方法参数传递给 bean。
在以下情况下单引号被保留:
- 在请求中将字符串作为消息正文传递
- 将路由 (
.setBody
) 中的正文设置(或覆盖)为常量
- 将路由 (
.setBody
) 中的正文设置(或覆盖)为表达式
- passing the body implicit to a bean
- 通过 bean 方法设置(或覆盖)主体 return 值
- 通过处理器 bean 设置(或覆盖)正文
仅当正文为passed explicitly to a bean method时,引号才被解释为字符串文字边界。
.bean(new EchoBean(), "echoBody(${body})")
成为你的情况
.bean(new EchoBean(), "echoBody('Re'quest')")
您可以尝试这个测试 class(Camel 3、JUnit 5)。它失败了,因为引号在最后一个带有显式参数的 bean 调用中丢失了。
package test.camel;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;
class QuoteTest extends CamelTestSupport {
public static final String MOCK_OUTPUT = "mock:output";
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from( "direct:start" )
.log("Reveived body: ${body}")
.setBody(constant("'Re'quest'"))
.log("Body overwritten in route: ${body}")
.bean(new EchoBean())
.log("Body overwritten through bean: ${body}")
.process().message( m -> m.setBody( "'Re'quest'" ) )
.log("Body overwritten through processor: ${body}")
.bean(new EchoBean(), "echoBody(${body})")
.log("Body overwritten through bean with methodparameter: ${body}")
.to(MOCK_OUTPUT);
}
};
}
@Test
void routeTest_quoteHandling_processed() throws Exception {
getMockEndpoint(MOCK_OUTPUT).expectedBodiesReceived("'Re'quest'");
template.requestBody("direct:start", "'Re'quest'");
assertMockEndpointsSatisfied();
}
static class EchoBean {
public String echoBody(final String messageBody) {
System.out.println("Expected: 'Re'quest', Actual: " + messageBody);
return messageBody;
}
}
}
它产生以下输出。如您所见,除了最后一个带有显式参数传递的 bean 调用外,所有步骤都保留了引号
09:00:53.521 [main] INFO route1 - Reveived body: 'Re'quest'
09:00:53.521 [main] INFO route1 - Body overwritten in route: 'Re'quest'
Expected: 'Re'quest', Actual: 'Re'quest'
09:00:53.527 [main] INFO route1 - Body overwritten through bean: 'Re'quest'
09:00:53.527 [main] INFO route1 - Body overwritten through processor: 'Re'quest'
Expected: 'Re'quest', Actual: Re'quest <<-- only when the body is passed as method parameter, the quotes are lost
09:00:53.529 [main] INFO route1 - Body overwritten through bean with methodparameter: Re'quest
import static java.lang.System.out;
import org.apache.camel.ExchangePattern;
import org.apache.camel.Message;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
class RequestReplyMessageSample {
class Replier {
String reply( final String /*Message*/ /*Exchange*/ request ) {
out.println( "\n[ERROR] Expected: 'Re'quest', Actual: " + request
+ " <-- Am I doing somethig wrong, is this a bug or a feature?\n" );
return String.format( "**** Replying to %s ****%n", request/*.getMessage()*/ /*.getBody( String.class )*/ );
}
} // Replier
private static final DefaultCamelContext cc = new DefaultCamelContext();
public static void main( final String... args ) throws Exception {
final Replier replier = new RequestReplyMessageSample().new Replier();
cc.setName( "Request Reply Sample" );
cc.addRoutes( new RouteBuilder() {
@Override
public void configure() {
from( "timer:start?repeatCount=1" )
.setExchangePattern( ExchangePattern.InOut )
.process().message( m -> m.setBody( "'Re'quest'" ) ) // EIP Request
.process().message( m -> print( "Request", m ) )
.log( "Requesting..." )
.log( "Replying..." )
// How to get Message (or Exchange) as argument in here?
.bean( replier, "reply(${body})" ) // EIP Requestor/Replier
.process().message( m -> print( "Reply", m ) ) // EIP Reply (in the body of the Message)
.setId( "Request/Reply" );
}
} );
cc.start();
Thread.sleep( 2000 );
cc.stop();
cc.close();
} // main()
static void print( final String endpoint, final Message m ) {
out.printf( "%s %s: %s%n", endpoint, m, m.getBody() );
} // print()
} // RequestReplyMessageSample
输出
...
Request Message: 'Re'quest'
[ple) thread #1 - timer://start] Request/Reply INFO Requesting...
[ple) thread #1 - timer://start] Request/Reply INFO Replying...
[ERROR] Expected: 'Re'quest', Actual: Re'quest <-- Am I doing somethig wrong, is this a bug or a feature?
Reply Message: **** Replying to Re'quest ****
...
这是一个feature. In this case, the single quotes at the start/end of the expression are interpreted as a string literal start/end。您需要添加另一个单引号让解析器将其视为字符(即 m.setBody("''Re'quest''")
)。
这是因为主体作为显式方法参数传递给 bean。
在以下情况下单引号被保留:
- 在请求中将字符串作为消息正文传递
- 将路由 (
.setBody
) 中的正文设置(或覆盖)为常量 - 将路由 (
.setBody
) 中的正文设置(或覆盖)为表达式 - passing the body implicit to a bean
- 通过 bean 方法设置(或覆盖)主体 return 值
- 通过处理器 bean 设置(或覆盖)正文
仅当正文为passed explicitly to a bean method时,引号才被解释为字符串文字边界。
.bean(new EchoBean(), "echoBody(${body})")
成为你的情况
.bean(new EchoBean(), "echoBody('Re'quest')")
您可以尝试这个测试 class(Camel 3、JUnit 5)。它失败了,因为引号在最后一个带有显式参数的 bean 调用中丢失了。
package test.camel;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;
class QuoteTest extends CamelTestSupport {
public static final String MOCK_OUTPUT = "mock:output";
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from( "direct:start" )
.log("Reveived body: ${body}")
.setBody(constant("'Re'quest'"))
.log("Body overwritten in route: ${body}")
.bean(new EchoBean())
.log("Body overwritten through bean: ${body}")
.process().message( m -> m.setBody( "'Re'quest'" ) )
.log("Body overwritten through processor: ${body}")
.bean(new EchoBean(), "echoBody(${body})")
.log("Body overwritten through bean with methodparameter: ${body}")
.to(MOCK_OUTPUT);
}
};
}
@Test
void routeTest_quoteHandling_processed() throws Exception {
getMockEndpoint(MOCK_OUTPUT).expectedBodiesReceived("'Re'quest'");
template.requestBody("direct:start", "'Re'quest'");
assertMockEndpointsSatisfied();
}
static class EchoBean {
public String echoBody(final String messageBody) {
System.out.println("Expected: 'Re'quest', Actual: " + messageBody);
return messageBody;
}
}
}
它产生以下输出。如您所见,除了最后一个带有显式参数传递的 bean 调用外,所有步骤都保留了引号
09:00:53.521 [main] INFO route1 - Reveived body: 'Re'quest'
09:00:53.521 [main] INFO route1 - Body overwritten in route: 'Re'quest'
Expected: 'Re'quest', Actual: 'Re'quest'
09:00:53.527 [main] INFO route1 - Body overwritten through bean: 'Re'quest'
09:00:53.527 [main] INFO route1 - Body overwritten through processor: 'Re'quest'
Expected: 'Re'quest', Actual: Re'quest <<-- only when the body is passed as method parameter, the quotes are lost
09:00:53.529 [main] INFO route1 - Body overwritten through bean with methodparameter: Re'quest