I am trying to use jms:publish-subscribe-channel to pub/sub on a single ActiveMQ topic. I am able to receive messages from ActiveMQ on the channel just fine, however when I publish to the channel the message body is null (when received by another application listening on the ActiveMQ topic). I was able to recreate the problem using spring-integration-samples->basic->jms. I modified outboundChannelAdapter.xml to use jms:publish-subscribe-channel instead of jms:outbound-channel-adapter. Is there another step needed in order to publish a simple string message? Here's my code change to outboundChannelAdapter.xml:
<stream:stdin-channel-adapter id="stdin" channel="stdinToJmsoutChannel"/>
<jms:publish-subscribe-channel id="stdinToJmsoutChannel" topic="requestTopic" />
<stream:stdout-channel-adapter id="stdout" channel="stdinToJmsoutChannel" append-newline="true"/>
I am not sure what you mean by "the message body is null".
I just made the exact same change to the sample and it worked fine for me...
Please type something and hit <enter>
foo
foo
I had to add -Dorg.apache.activemq.SERIALIZABLE_PACKAGES=* to the command line because activemq needs whitelisting for classes (the whole message is serialized in jms-backed channels).
Related
I try to use EventHub Go client to send a simple "hello world" event but got this error message:
*Error{Condition: amqp:internal-error, Description: The service was unable to process the request; please retry the operation. For more information on exception types and proper exception handling, please refer to http://go.microsoft.com/fwlink/?LinkId=761101 TrackingId:be0c66437a1447b7accdc113c84955dd_G5, SystemTracker:gateway5, Timestamp:2021-07-10T21:28:48, Info: map[]}
The code is exactly the same as this sample code here: https://github.com/Azure/azure-event-hubs-go
The SO thread I found which somehow has similar error message is here Getting "amqp:internal-error" when peeking messages from Azure Service Bus Queue using AMQP, rhea and Node, but it is for Service Bus and Node client.
Any idea why this issue occured?
This error is pretty non-descriptive.
One way to trigger is to specify an EventHubs connection string without an EntityPath=<event hub name> in it.
So if you're using a broker level connection string you'll need to specify the EventHub you're attempting to connect to by adding EntityPath=eventHubName. The readme snippet does list this, but the error is admittedly not great in that situation.
I've filed this issue to at least improve the error message in that case, as it doesn't really lead you to what's wrong.
https://github.com/Azure/azure-event-hubs-go/issues/222
I'm currently implementing a flow on a Spring Integration-based (ver. 3.0.1.RELEASE) application that requires to store messages on a JMS queue to be picked up later.
For that, I've been trying to use a Spring Integration JMS Inbound Channel Adapter with a custom selector, and then picking up the message from the queue by changing the JMS selector of the JMSDestinationPollingSource to some matching ID included as a header property.
One of the requirements for this is that I cannot add a new service or a JAVA method, so I've been trying to sort it out using a Control Bus, but keep receiving the same error when I send the message to set the messageSelector to something different.
Inbound Channel Adapter definition:
<int-jms:inbound-channel-adapter id="inboundAdapter"
channel="inboundChannel"
destinationName="bufferQueue"
connection-factory="connectionFactory"
selector="matchingID = 'NO VALUE'">
<int:poller fixed-delay="1000"/>
</int-jms:inbound-channel-adapter>
Message:
#'inboundAdapter.source'.setMessageSelector("matchingID = 'VALUE'")
Error:
EvaluationException: The method 'public void org.springframework.integration.jms.JmsDestinationPollingSource.setMessageSelector(java.lang.String)' is not supported by this command processor. If usign the Control Bus, consider adding #ManagedOperation or #ManagedAttribute.
Which, AFAIK, means that the JmsDestinationPollingSource class is not Control Bus manageable, as it's not passing the ControlBusMethodFilter.
Is this approach nonviable, or is there something I'm missing? Is there any way to set the selector dynamically using SI XML configuration files only?
First of all it is strange to use Java tool and don't allow to write code on Java...
But that is your choice, or as you said requirements.
Change the employer! ;-)
That's correct: Control Bus allows only #ManagedOperation and #ManagedAttribute method. Since JmsDestinationPollingSource.setMessageSelector. We can make it like that. But does it make so much sense if we can reach it a bit different approach?
<int:outbound-channel-adapter id="changeSelectorChannel"
ref"inboundAdapter.source method="setMessageSelector"/>
where a new selector expression should be as a payload of the Message to this channel.
I have a client in NodeJS using the MQTT module (mqtt.js) to communicate with a topic of WebSphere MQ, redirected to a queue : I need the result to be on a queue so I use a topic between the source and the destination (since MQTT protocol communicate only with topics).
So we have :
NodeJS (source) -> Topic of Websphere MQ (intermediate) -> Queue of Websphere MQ (destination)
The problem is that the received messages on the queue of WebsphereMQ are MQHRF2 format but I need MQSTR.
I did not find any property in mqtt.js side to specify the format.
I supposed we can force it with IBM Websphere MQ, but how ? Can I create a channel or anything for this use, that's to say convert the receiving format ?
Thanks in advance for your help !
Configuration :
MQTT.js v3
WebSphere MQ v7.5
Constrains :
WebSphere MQ must be v7.5 (so I can't upgrade to v8 to use mqlight)
Better stay with the module MQTT.js
It works correctly when I publish directly on a topic via the WebSphere MQ explorer. However, it fails when I publish from the NodeJS application.
I tried both methods listing in the comments but I found a weird thing : The result is different according to if I use MQExplorer (what I always used) or the MQ console :
On the MQ Explorer :
On the MQ Console, with the command : amqsbcg QUEUE_MQTT_VERIF MQTTVerification :
As you can see, in the console, the format field is empty, whereas on the MQExplorer it is MQHRF2. The messages are also different.
So the result on the MQConsole is right whereas the MQExplorer still shows a wrong result after the changes.
Note that the result is right only if changes has been done on both :
Subscription : ALTER SUB(APPLE.PRICES) PSPROP(NONE)
Queue : ALTER QLOCAL(PRICES) PROPCTL(NONE)
Maybe the source of the problem is just the display on MQExplorer software ?
EDIT:
The difference between MQExplorer and MQConsole was due to the parameter in MQ Explorer : Window -> Preferences -> WebSphereMQ Explorer -> Message properties -> Uncheck "Display message properties".
When redirecting publications made on a topic to a queue you probably have some definitions like this:-
DEFINE QLOCAL(PRICES)
DEFINE TOPIC(APPLES) TOPICSTR('Price/Fruit/Apples')
DEFINE SUB(APPLE.PRICES) TOPICOBJ(APPLES) DESTCLAS(PROVIDED) DEST(PRICES)
which redirects publications made on the topic string 'Price/Fruit/Apples' to the queue PRICES.
What you will find with such a set up however, is that the topic string is added to the message by the queue manager and thus adds an MQRFH2 header onto the front of your published message.
Message Descriptor (MQMD)
Report :00000000
Message Type :8 (Datagram)
Format :'MQHRF2 '
Priority :0
Persistence :0 (Not Persistent)
Message Id :414D51204D51473120202020202020202D77835720003702
'AMQ MQG1 -w.W .7.'
ReplyToQ :' '
ReplyToQMgr :'MQG1 '
[ 102 bytes] Message Content
<mqps>
<Top>
Price/Fruit/Apples
</Top>
</mqps>
Apples are $2/kilo
To remove this without changing the application reading from the queue, make this alteration to the subscription.
ALTER SUB(APPLE.PRICES) PSPROP(NONE)
This stops the queue manager even putting the topic string into the message in the first place.
From your MQ Explorer screenshot, it can be seen that the MQRFH2 is still present after the SUB is changed to PSPROP(NONE) because there is another property present - mqtt.clientid. Since there are other items in the MQRFH2 as well as the topic string, then the SUB change will not remove those - only the topic string added by the queue manager. In that case, you should try the following.
If alternatively you want to have the topic string there sometimes and only remove it for applications that don't want to see it, you can make a similar change to the queue, which can be over-ridden in application code to force the properties to be delivered to the application, but otherwise they won't be. This would also allow you to read any existing messages that had already been published (the change to the SUB isn't retrospectively applied to messages that are already on the queue).
ALTER QLOCAL(PRICES) PROPCTL(NONE)
This will mean that applications that don't specifically request MQGMO_FORCE_RFH2 will see the message without the MQRFH2. The amqsbcg sample is one such application.
If an application codes MQGMO_FORCE_RFH2 it will still be able to see the properties in an MQRFH2 header because it has explicitly asked for that. You cannot stop that by changing the queue.
Your problem is only now with the way MQ Explorer chooses to display the message. There is a parameter in MQ Explorer : Window -> Preferences -> WebSphereMQ Explorer -> Message properties -> Uncheck "Display message properties" which will stop it forcing them to be an MQRFH2, and then you'll be all good.
I'm currently working on my first SpringXD Stream. It should receive a message on an MQTT topic, do a HTTP POST on a service and publish this result on another MQTT topic.
Currently I'm stuck at publishing to a different MQTT topic than the initial one.
This is my stream:
stream create test --definition "in:mqtt --url='tcp://hivemq:1883' --topics='+/+/+/my/downlink' --username='test' --password='test' --clientId='client_downlink'
| header-enricher --headers={\"mqtt_topic\":\"headers['mqtt_topic'].replace('/downlink', '/uplink')\"}
| out:mqtt --url='tcp://hivemq:1883' --username='test' --password='test' --clientId='client_uplink'" --deploy
The approach is to replace "/downlink" by "/uplink" in the header 'mqtt_topic' for Publishing but header-enricher doesn't overwrite existing header values, so the publish is made on the same topic as we received the message.
Any Idea how I could achieve this?
I am working on an enhancement for this. Meanwhile you can edit the header-enricher groovy script modules/processor/header-enricher/config/header-enricher.groovy and make this change:
si.'header'(name:k,expression:v,overwrite:true)
I'm seeing weird behaviour when sending data through my channels. I'm using SI gateway when sending a message to be processed. The gateway is setup as below
<integration:gateway id="rptPubGateway"
default-request-channel="rptPubInChannel"
default-reply-channel="rptOutputAvailableChannel"
default-reply-timeout="60000"
service-interface="xxxx.RptPubGateway" />
The reply channel is being set up as a publish/subscribe channel
<integration:publish-subscribe-channel id="rptOutputAvailableChannel" />
The last service that processes the message is being declared as below
<integration:service-activator input-channel="rptOutputAvailableChannel" ref="requestMessageHandler" method="rptIsDone" output-channel="nullChannel"/>
Now, the issue that i have is that while the code works fine most of the time, it fails sometimes. When everything works fine the last component processing my message is PublishSubsChannel
PublishSubscribeChannel - preSend on channel 'rptOutputAvailableChannel'
but when it fails the last component becomes BridgerHandler
BridgeHandler#e851a798' sending reply Message:
I should mention that there are no exceptions being thrown while processing my message. (after the failure I can always resend the same message and everything will work OK)
I'm not sure how that BridgerHandler gets created. From what I know this bridge gets created for pub/subs channels but then why I don't see it in the log when everything works fine ?
I'd appreciate any help
When you say "fails" what do you mean?
What are the other consumers on rptOutputAvailableChannel?
The BridgeHandler you see is an internal bridge to the message's replyChannel header, which is where the reply ultimately must go. When explicitly sending to rptOutputAvailableChannel, the bridge handler is always invoked to get the reply to the message's temporary reply channel.