I'm using the spring integration xmpp module to write a custom implementation of a 3rd party Server connecting to GCM cloud services, as in GCM Cloud Connection Server (XMPP).
So far I've successfully connected to the GCM server, however when I send a message to the server I end up with something like:
<message id="m-1366082849205" to="REGISTRATION_ID">
<body>{"hello":"world"}</body>
</message>
, but I need to send something like this:
<message id="">
<gcm xmlns="google:mobile:data">
{
"to":"REGISTRATION_ID",
"message_id":"m-1366082849205"
"data":
{
"hello":"world",
}
}
</gcm>
</message>
I use the latest SI version, 4.0.4, this is my configuration in the xml:
<int-xmpp:outbound-channel-adapter
id="gcmOutboundAdapter" channel="gcmOutboundNotificationChannel"
xmpp-connection="gcmConnection" auto-startup="true"/>
I'm sending messages with the usual MessageBuilder like this:
Message<String> xmppOutboundMsg = MessageBuilder.withPayload(xmppPayload)
.setHeader(XmppHeaders.TO, REGISTRATION_ID)
.build();
where xmppPayload is a json string.
I need to configure/override the way the xmpp message is composed, what is the best practice to achieve the result? Should I override the class implementing int-xmpp:outbound-channel-adapter with a custom service activator, is there anyway to configure the way the xmpp message is composed?
Thanks for any help.
<gcm xmlns="google:mobile:data">
is a extended content element (see RFC 6120 8.4), which is modelled as PacketExtension in Smack. Do not subclass message, instead create a GCMPacketExtension class and add a instance of it to your message
message.addPacketExtension(gcmPackExtension)
The format of the message is hard-coded in the Smack Message.toXML()
method (we use the smack library underneath).
See @Flow's answer.
Then, subclass ChatMessageSendingMessageHandler
, overriding handleMessageInternal()
- pretty much copy the code and set the extension after the message is created.
The easiest way to configure your custom handler is probably to put it in a chain
...
<chain input-channel="gcmOutboundNotificationChannel">
<bean class="foo.MyChatMessageSendingMessageHandler">
<constructor-arg ref="gcmConnection" />
</bean>
</chain>
Or you can wire it up as a top level bean and inject it into a ConsumerEndpointFactoryBean
.
Feel free to open a New Feature JIRA Issue and we'll consider adding an extension point to make this a bit easier.
Until we introduce the PackExtension
injection, you can overcome it with custom <transformer ref="">
, because the <int-xmpp:outbound-channel-adapter>
can accept org.jivesoftware.smack.packet.Message
as a 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;
}
}
Please, raise an issue about PackExtension
support.
-->
<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" />