【问题标题】:Basic flow results in NullPayloadNullPayload 中的基本流结果
【发布时间】:2018-04-26 14:37:03
【问题描述】:

我是 Mule 的新手,我正在尝试让“Mule in Action”一书中的第一个示例正常工作。

我正在使用 Mule 3.9 和 Anypoint Studio 6.4.1。在第 1 章中,他们描述了我创建的一个非常基本的 product_registration 流程,如下所示:

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

<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:jms="http://www.mulesoft.org/schema/mule/jms" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
    xmlns:spring="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core 
http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http 
http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/jms 
http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd">
    <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8880" basePath="products" doc:name="HTTP Listener Configuration"/>
    <jms:activemq-connector name="Active_MQ" username="admin" password="admin" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"/>
    <flow name="product_registrationFlow">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
        <logger level="INFO" doc:name="Logger Before"/>
        <byte-array-to-string-transformer doc:name="Byte Array to String"/>
        <logger level="INFO" doc:name="Logger After"/>
        <jms:outbound-endpoint doc:name="JMS" queue="products"/>
    </flow>
</mule>

以及随附的功能测试:

@Test
public void testCanRegisterProducts() throws Exception {

    LocalMuleClient client = muleContext.getClient();

    String productAsJson = "{ \"name\":\"Widget\", \"price\": 9.99, \"weight\": 1.0, \"sku\": \"abcd-56789\" }";

    MuleMessage source = new DefaultMuleMessage(productAsJson, muleContext);
    client.dispatch("http://localhost:8880/products", source);

    MuleMessage result = client.request("jms://products", RECEIVE_TIMEOUT);

    assertNotNull(result);
    assertFalse(result.getPayload() instanceof NullPayload);
    assertEquals(productAsJson, result.getPayloadAsString());
}

当我运行测试时,它在最后一个断言处失败,因为实际有效负载是:

{NullPayload}

如果我直接查看 ActiveMQ,我会看到该有效负载。如果我手动发布到 Mule(使用 Chrome 中的 Poster 之类的工具,仅设置标头 Content-Type: application/json),则有效负载是有效的 JSON,我可以让测试通过(因为它正在从Poster 发布的队列及其创建的消息位于队列末尾,负载为 {NullPayload}。

有人能解释一下为什么从 JUnit 测试调用流程失败,但在使用像海报这样的工具调用时似乎可以工作吗?

更新:在 Pierre B 的帮助下,我成功了。 FunctionalTestCase 中 MuleMessage 的初始化更新如下:

    MuleMessage source = new DefaultMuleMessage(productAsJson, muleContext);
    source.setProperty("Content-Type", "application/json", PropertyScope.INBOUND);
    source.setProperty("Content-Length", Integer.valueOf(productAsJson.length()), PropertyScope.INBOUND);

【问题讨论】:

  • "如果我直接查看 ActiveMQ,我会看到该有效负载" 您的意思是在 JUnit 中运行测试后,您会在 ActiveMQ 中看到 NullPayload,还是看到您的 JSON 内容? “因为它正在从 Poster 发布的队列中获取待处理消息,并且它创建的消息位于有效负载 {NullPayload} 的队列末尾”您的意思是您首先使用 Poster 发布了一条消息,然后运行测试,它通过了但是NullPayload 消息是否仍在队列中?
  • 是的,如果我查看 ActiveMQ(使用 ActiveMQ 管理控制台),使用测试用例创建的消息的有效负载实际上是“{NullPayload}”,但如果我运行 Mule 并使用海报发送相同的 JSON 到相同的 HTTP 入站端点,JSON 在 ActiveMQ 管理控制台中正确显示。您对我如何让测试“通过”的理解也是正确的 - 队列变得乱序,测试用 {NullPayload} 发布一条消息,然后读取之前用海报发布的一条消息并通过 - 消息来自测试的仍然在队列中。
  • 好的,这可能是由于您使用 MuleClient 生成消息的方式造成的,Mule 可能无法正确识别它。输出之前/之后的日志是什么?如果没有给出任何内容,请将您的记录器配置为使用message="#[message]"message="#[payload]"输出当前消息或有效负载
  • 谢谢@PierreB。我会试一试并报告——我同意你的逻辑并尝试调试——我在构建后立即看到正确的有效负载和原始有效负载,但我无法花足够的时间来了解调度调用中发生的事情。我怀疑这与 Mule 不知道 MuleMessage 包含 JSON 有关?
  • 正是我的想法,我刚刚添加了一个关于此的答案。您可能需要使用 MuleMessage 的 dispath 调用来指定内容类型。

标签: mule anypoint-studio


【解决方案1】:

你说过当你使用外部工具而不是 MuleClient 发布消息时它可以工作:

在Chrome中使用Poster之类的工具,只设置header Content-Type: application/json

尝试将相同的标题添加到您的 MuleMessage,例如:

MuleMessage source = new DefaultMuleMessage(productAsJson, muleContext);

# define the headers
Map<String, Object> headers = new HashMap<String, Object>(1);
headers.put("Content-Type", "application/json");
headers.put("Content-Length", sourceLength);

# add the headers as function parameter
client.dispatch("http://localhost:8880/products", source, headers);

编辑:正如@sceaj 指出的那样, Content-Type 和 Content-Length 标头都是必需的。

【讨论】:

  • 有关如何传递标头的详细信息,请参阅stackoverflow.com/questions/27149882/…
  • 我刚试过这个,不幸的是它失败了,说实际的 JMS 消息内容仍然是 {[NullPayload]}。我将在今天晚些时候尝试记录并更新。
  • 比较日志的输出,我仍然需要添加“Content-Length”标头(除了 Content-Type)。如果您更新答案@PierreB,我会接受。
  • 很高兴看到它有效;)我按照您的建议进行了编辑,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-01
  • 2022-11-29
  • 2012-05-18
  • 1970-01-01
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多