【问题标题】:Spring integration XMPP and Google Cloud MessagingSpring 集成 XMPP 和 Google Cloud Messaging
【发布时间】:2014-12-25 17:06:54
【问题描述】:

我正在使用 spring 集成 xmpp 模块编写连接到 GCM 云服务的第 3 方服务器的自定义实现,如 GCM Cloud Connection Server (XMPP)。

到目前为止,我已经成功连接到 GCM 服务器,但是当我向服务器发送消息时,我最终会得到如下信息:

<message id="m-1366082849205" to="REGISTRATION_ID">
<body>{"hello":"world"}</body>
</message>

,但我需要发送如下内容:

  <message id="">
  <gcm xmlns="google:mobile:data">
  {
      "to":"REGISTRATION_ID",
      "message_id":"m-1366082849205"
      "data":
      {
          "hello":"world",
      }
  }
  </gcm>
</message>

我用的是最新的SI版本,4.0.4,这是我在xml中的配置:

<int-xmpp:outbound-channel-adapter
    id="gcmOutboundAdapter" channel="gcmOutboundNotificationChannel"
    xmpp-connection="gcmConnection" auto-startup="true"/>

我正在使用通常的 MessageBuilder 发送消息,如下所示:

Message<String> xmppOutboundMsg = MessageBuilder.withPayload(xmppPayload)
        .setHeader(XmppHeaders.TO, REGISTRATION_ID)
        .build();

其中 xmppPayload 是一个 json 字符串。

我需要配置/覆盖 xmpp 消息的组成方式,实现结果的最佳实践是什么?我是否应该使用自定义服务激活器覆盖实现 int-xmpp:outbound-channel-adapter 的类,是否可以配置 xmpp 消息的组成方式?

感谢您的帮助。

【问题讨论】:

标签: xmpp spring-integration google-cloud-messaging


【解决方案1】:

-->

<int:chain input-channel="gcmOutboundNotificationChannel">
    <!--<int:transformer ref="toGcmTransformer" output-channel="gcmOutboundNotificationChannel"/>-->
    <bean class="com.payumoney.cardhash.service.MyMessageSendingMessageHandler">
        <constructor-arg ref="gcmConnection" />
    </bean>
</int:chain>
<int:transformer id="testTransformer" ref="toGcmTransformer" input-channel="gcmInboundNotificationChannel"
         method="doTransform" output-channel="gcmOutboundNotificationChannel"/>
<!--<int:transformer ref="toGcmTransformer" output-channel="gcmOutboundNotificationChannel"/>-->

<int-xmpp:outbound-channel-adapter
    id="gcmOutboundAdapter" channel="gcmOutboundNotificationChannel"
    xmpp-connection="gcmConnection" auto-startup="true"/>

<int:chain input-channel="gcmInboundNotificationChannel">
    <bean class="com.payumoney.cardhash.service.PayumoneyNotificationListeningEndpoint">
        <constructor-arg ref="gcmConnection" />
        <property name="outputChannel" ref="gcmOutboundNotificationChannel" />
    </bean>
</int:chain>

<int-xmpp:inbound-channel-adapter 
    id="gcmInboundAdapter"  channel="gcmInboundNotificationChannel" 
    xmpp-connection="gcmConnection" extract-payload="true" auto-startup="true" />

【讨论】:

  • 带有解释的答案更有可能被 OP 接受,并吸引投票。
【解决方案2】:

在我们引入PackExtension 注入之前,您可以使用自定义&lt;transformer ref=""&gt; 来克服它,因为&lt;int-xmpp:outbound-channel-adapter&gt; 可以接受org.jivesoftware.smack.packet.Message 作为消息payload:

<transformer ref="toGcmTransformer" output-channel="gcmOutboundNotificationChannel"/>

<int-xmpp:outbound-channel-adapter
    id="gcmOutboundAdapter" channel="gcmOutboundNotificationChannel"
    xmpp-connection="gcmConnection" auto-startup="true"/>

public class ToGcmTransformer extends AbstractTransformer {


   protected Object doTransform(Message<String> message) throws Exception {
        String to = message.getHeaders().get(XmppHeaders.TO, String.class);
        xmppMessage = new org.jivesoftware.smack.packet.Message(to);
        xmppMessage.setBody(message.getPayload());
        xmppMessage.addPacketExtension(gcmPackExtension);
        return xmppMessage;
   }

}

请提出关于PackExtension 支持的问题。

【讨论】:

    【解决方案3】:

    消息的格式在 Smack Message.toXML() 方法中是硬编码的(我们使用下面的 smack 库)。

    查看@Flow 的回答。

    然后,子类ChatMessageSendingMessageHandler,覆盖handleMessageInternal() - 几乎复制代码并在创建消息后设置扩展。

    配置自定义处理程序的最简单方法可能是将其放入chain...

    <chain input-channel="gcmOutboundNotificationChannel">
        <bean class="foo.MyChatMessageSendingMessageHandler">
            <constructor-arg ref="gcmConnection" />
        </bean>
    </chain>
    

    或者您可以将其连接为顶级 bean 并将其注入到 ConsumerEndpointFactoryBean。

    请随时打开New Feature JIRA Issue,我们会考虑添加一个扩展点以简化此操作。

    【讨论】:

    • 永远不要子类化消息! gcm 是一个 PacketExtension(在 Smack 术语中)。另见我的answer。 BTW Smack 不再由 Jive 软件维护。它在 ignite realtime 的开源保护伞下。
    • 感谢@Flow - 更新了我的答案以指向您的答案,并保留了 OP 在 Spring Integration 中设置该选项所需的代码。我们绝对应该打开一个扩展点来允许添加扩展。
    • 感谢您的回答,我检查了 ChatMessageSendingMessageHandler 的实现,并且如果它是 org.jivesoftware.smack.packet.Message 类型,handleMessageInternal 将对消息进行简单的传递,所以我不需要子类。
    • 确实如此。我反映在我的回答中
    【解决方案4】:

    &lt;gcm xmlns="google:mobile:data"&gt; 是一个扩展的内容元素(参见 RFC 6120 8.4),它在 Smack 中被建模为 PacketExtension。不要子类化消息,而是创建一个 GCMPacketExtension 类并将其实例添加到您的消息中

    message.addPacketExtension(gcmPackExtension)
    

    【讨论】:

    • 请参阅@GaryRussell 的回答,了解如何对消息处理程序进行子类化和配置以添加此扩展。
    • 感谢@Flow,这解决了我的问题。我这样编写消息: Message xmppMessage = new Message(); xmppMessage.addExtension(new GcmPacketExtension(xmppPayload));并将其发送到出站适配器。
    • 太好了!我无法添加更多 +1,但如果分享 GcmPacketExtension 会很棒。哪个罐子(工件)包含它?
    • @ArtemBilan gcmPacketExtension 是该示例末尾的类 link 。链接中的行为正是我所需要的,所以我只是把它放在我的实现中并以最简单的方式调用它,因为我必须尽快启动一个工作服务器,以便在客户端进行早期测试。跨度>
    • Smack 现在提供了一个 GcmPacketExtension 类和提供者 github.com/igniterealtime/Smack/commit/…
    猜你喜欢
    • 2014-03-02
    • 1970-01-01
    • 2015-12-23
    • 2019-03-08
    • 2016-11-05
    • 1970-01-01
    • 2018-09-06
    • 2016-08-07
    • 2020-08-13
    相关资源
    最近更新 更多