Best Of
Re: How to get a Map (java.util) of internal properties of a JCSMP message (in java)
For #1 Metadata, there are actually two sub-sections:
- Message headers
- User Properties
Unfortunately, there are no convenience functions to walk through every header in the message and provide it in a Map. You'll just have to crawl through all the get
and is
methods on the Message. That's what I did for this post from a few years ago:
I should probably update it since (as you mentioned) there are new metadata available (RGMID, Trace Context, etc.)
Re: How to see information on each message in a queue
Yeah, if there's millions or billions of messages, this approach could/would be quite inefficient. Another option is to use the more recent broker feature of copying a message from one queue to another. If you happen to know the message's Replication Group Message Id, you can use that to copy the message. This is different than the Message ID above (which is the message spool ID in the broker).
For example, let's say I have a billion messages on my queue, but I just want to browse the most recent one. I can use the CLI command show queue q1 message-vpn default messages newest detail
Name: q1 Message VPN: default Message Id: 4187008 Priority: n/a Date spooled: Apr 12 2024 09:25:33 UTC Replication Group Message Id: rmid1:2cf0b-4a19b6301d4-00000000-003fe380 <--- Sequence Number: n/a Expiry Time: never Delivery Eligible Time: now Dead Message Queue Eligible: yes Content: 0.0000 MB Attachment: 0.0003 MB Replicated: no Replicated Mate Message Id: n/a Sent: no Redeliveries: 0 PartitionKey: PartitionKeyHash: 0
I could make a temporary queue tempQ
. And then run the CLI commands:
enable admin message-spool message-vpn default copy-message source queue q1 destination queue tempQ message rmid1:2cf0b-4a19b6301d4-00000000-003fe380 show tempQ Queue Name Messages Spool Bind Status Message VPN Spooled Usage(MB) HWM (MB) Count I E A S D P tempQ default 1 0.00 0.00 0 U U E N D N
Then browse/consume that.
If you know how to do SEMPv1, the equivalent copy command would be:
<rpc> <admin> <message-spool> <vpn-name>default</vpn-name> <copy-message> <source/> <queue-name>q1</queue-name> <destination/> <queue-name>tempQ</queue-name> <message/> <replication-group-msg-id>rmid1:2cf0b-4a19b6301d4-00000000-003fe380</replication-group-msg-id> </copy-message> </message-spool> </admin> </rpc>
Re: Timestamp when queue received message
The receive timestamp is the time the API received the message. That's different to when the message was spooled, as the consumer could have been offline.
There are 3 possible times of interest here:
- Time of send. Set by the sending API;
- Time of spooling. Set by the broker;
- Time of receive. Set by the receiving API.
To get this receive timestamp, you'll need to set the generate receive timestamps session property (GENERATE_RCV_TIMESTAMPS in JCSMPProperties)
Weird chars at start of text payload!?
Hi all! I'm making a definitive post about this because it's been asked countless times, and I still can't find a good "one-page" reference response. The issue: sometimes you'll see weird characters at the beginning of your text payload. For example, this is from the JCSMP HelloWorld sample:
Destination: Topic 'solace/samples/jcsmp/hello/aaron'
Priority: 4
Class Of Service: USER_COS_1
DeliveryMode: DIRECT
Message Id: 6
Binary Attachment: len=26
1c 1a 48 65 6c 6c 6f 20 57 6f 72 6c 64 20 66 72 ..Hello.World.fr
6f 6d 20 41 61 72 6f 6e 21 00 om.Aaron!.
Or if you just print out the raw payload as a String: ∟↓Hello World from Aaron!
See those first two bytes? 0x1c and 0x1a? What are they? In Solace world, when sending a TextMessage, you are not just sending a raw String as binary payload. The API is actually constructing a Structured Data Type (SDT) formatted message, where there is a single field (the String) in the container. Those first few bytes (could be 2-6 I think) define the size of the String contained within the SDT TextMessage.
Solace messages can be one of: TextMessage, BytesMessage, MapMessage, or StreamMessage. Thanks to JMS for these.
So your receiver/consumer should ideally check what type of message it is receiving and deal with it appropriately. In JCSMP Java, this looks something like:
public void onReceive(BytesXMLMessage message) { if (message instanceof TextMessage) { TextMessage msg = (TextMessage)message; String payload = msg.getText(); // do more } else if (message instanceof BytesMessage) { BytesMessage msg = (BytesMessage)message; byte[] payload = msg.getData(); // NOT getBytes() strangely, that gets the XML payload // are you sure the payload is a string? String strPayload = new String(payload, StandardCharsets.UTF_8); // more } else if (message instanceof MapMessage) { // not often used anymore MapMessage msg = (MapMessage)message; SDTMap map = msg.getMap(); } else if (message instanceof StreamMessage) { // not often used anymore StreamMessage msg = (StreamMessage)message; SDTStream stream = msg.getStream(); } else { // should be impossible, these are the only 4 types } . . .
The newer Java API hides this stuff from you, BTW. Other APIs, I'm not sure..?
But in JavaScript/NodeJS, same thing… you need to check what type of message you've received and deal with appropriately:
session.on(solace.SessionEventCode.MESSAGE, function (message) { if (message.getType() == solace.MessageType.TEXT) { var strPayload = message.getSdtContainer().getValue(); // do stuff } else if (message.getType() == solace.MessageType.BINARY) { var payload = message.getBinaryAttachment(); // binary attachment, could be String or Uint8Array // do stuff } else { // either a stream or a map SDT } . . .
See JavaScript docs on MessageType, and on getType().
A lot of people stumble into this with JavaScript since getBinaryAttachment()
returns (usually) a String. And might not notice if their publisher app (also probably JavaScript) is sending plain Strings as raw binary / BytesMessage, instead of an SDT TextMessage. This issue usually shows up when you start mixing different types of publisher languages, APIs, or protocols, and the apps are not all formatting messages the exact same way. (e.g. Java publisher TextMessages, JavaScript consumer).
Oh, and if you want to send text messages with JavaScript, do something like this:
var msg = solace.SolclientFactory.createMessage(); msg.setDestination(solace.SolclientFactory.createTopicDestination("hello/world")); msg.setSdtContainer(solace.SDTField.create(solace.SDTFieldType.STRING, "here is my text."));
Note that this publishing at structured text vs. binary also applies to REST/HTTP Messaging publishers. This is binary:
curl -u user:pw http://localhost:9000/hello/world -d 'hello bytes message'
And this is a structured TextMessage:
curl -u user:pw http://localhost:9000/hello/world -H 'content-type:text/plain' -d 'hello text message'
See Solace REST encoding docs here on HTTP Content-Type Mapping to Solace Message Types.
Finally, the broker has some smarts built into it for helping with protocol translation. For example, if subscribing with an MQTT client on topic hello/world
, and I publish the two (SMF) HTTP messages above (or equivalently, one binary message and one text message), then the MQTT consumer receives both string payloads correctly (no weird extra chars):
I really hope this post helps people, and I've included enough keywords for Google to pagerank it highly..! 😁
Re: Did anyone solve the problem with argocd ?
Hi @Matthias,
Reading this error it doesn't seem like a Solace specific thing. Can you try what they recommended here:
and specify it as a chart instead of a repo?Hope that helps!
Now Available: PubSub+ Messaging API for .NET & JavaRTO with Mac M-series Support
I am pleased to announce that as of the latest release of both our .NET (v. 10.23.0) and JavaRTO (v. 10.6.0) APIs, they now support Mac M-series processor so developers can now use these APIs when developing applications on the latest Mac hardware.
They can be downloaded through all the regular channels such as:
- Solace Downloads
Page: - Solace Products Page:
As of this writing, we now have added support for Mac M-series processors to the following APIs:
- C API
- .NET
- JavaRTO
- Go
The last outstanding API that does not yet have support is our Python API which we expect to be available towards the end of the first half of this year. A similar post will be created once it is available for download so stay tuned!
Cheers,
MV
Make original client-ip visible inside Solace when running in Kubernetes
Hello everyone,
we are running Solace in a Kubernetes Cluster. We have the issue that all connected clients are only shown with a IP address from the internal K8S Cluster subnet (e.g. 10.240.0.0/24).
Our setup is as follows:
- We are using Traefik as IngressController
- Traefiks service is set to be of type LoadBalancer (getting assigned a public IP)
- The L4 LoadBalancer is provided by Yawol
- The service of the Solace instance is set to ClusterIP
- We define a (set of) IngressRouteTCP to route TCP traffic towards Solace through Traefik.
On the Yawol-LoadBalancer and Traefik I have the option to enable the "Proxy Protocol" which provides a convenient way to safely transport connection information such as a client's address across multiple layers of NAT or TCP proxies (see
)This works up until Traefik, once the packages get routed towards the Solace Broker the information seems to get lost (or Solace does not handle the Proxy Protocol ?) and the clients are only shown with the kubernetes cluster internal IP.
My questions would be:
- Does someone know if Solace has envoy support for proxy protocol ?
- Do I have other options to get the client ip without changing my setup ?
- Maybe someone knows if this would work if I skip the IngressController in the middle and assign directly to the Solace Service a public IP ?
I tried to draw my setup - maybe this helps to showcase what I am trying to achieve
Greetings,
Jan-Filip.
—-
Additional links:- Documentation for Traefik proxy protocol:
Re: Solace PubSub+ IBM MQ Connector to send from solace through jms with non jms consumer
Hi Chewaiwu,
IBM Documentation discusses the MQRFH2 header and interoperability with non-JMS applications here
Quote of interest: "The MQRFH2 is optional, and its inclusion in an outgoing message is governed by the TARGCLIENT flag in the JMS Destination class. [ … ] Normally, omit the MQRFH2 when sending a message directly to a non-JMS application. This is because such an application does not expect an MQRFH2 in its IBM MQ message."
TARGCLIENT or TargetClient can be set in 2 different ways on a destination.
If using a JNDI Destination, targetClient
can be set on the JNDI Queue/Topic.
Otherwise, targetClient
can be specified directly in the connector config when using a URI formatted queue or topic. For instance:
spring: cloud: stream: bindings: input-0: destination: Solace/Queue/0 # Queue name binder: solace output-0: destination: queue:///DEV.QUEUE.1?targetClient=1 binder: jms
I hope this helps
Re: Is it possible to receive messages from a queue in a FILO way?
Hi @l16phill, if you just want to see the latest message on a queue, another option would be to configure an LVQ (Last Value Queue, set its spool quota to 0MB), and give it the exact same subscriptions as your primary queue (or if you're publishing to the other queue directly, then add that queue's network topic to the LVQ: #P2P/QUE/<queueName>
). Then you can just repeatedly browse the LVQ and it will show the last message currently received.
There is no way to only get the last n messages off a queue… you'd have to browse through everything in a FIFO manner.
Re: Favourite Solace Swag
I have'nt got any. but as per images shared above It looks like T-Shirt