I have a Springboot application using Apache Camel AMQP component to comsume messages from a Solace Queue. To send a message to the Queue I use Postman and the Solace REST API. In order to differentiate the message type I add Content-Type to the header of the Http request in Postman. I used SDKPerf to check the message header consumed from solace and the message header is found under "HTTP Content Type" along with other headers.
However, I can't seem to find a way to get this Content-Type from Camel Side. In the documentation it says
String header = exchange.getIn().getHeader(Exchange.CONTENT_TYPE, String.class);
However this always produces null. Any Ideas how to get the message properties in Camel?
EDIT: I think it's actually due to the fact that Camel is using QPid JMS, and there is no JMS API way of getting the Content Type, it's not in the spec. Even though AMQP 1.0 does support content-type
as a property. But yeah, my suggestion of a custom property below is still probably the way I would go.
Edited for clarity & corrections. TL/DR: use a custom user property header.
The SMF Content Type header in the original (REST) message is passed through to the consumed AMQP message as a property content-type
, however the JMS API spec does not expose this; there is no way in standard JMS to retrieve this value. It is, however, used by the broker to set the type of message (e.g. TextMessage). Check "Content-Type Mapping to Solace Message Types" in the Solace docs.
Using Solace's SDKPerf AMQP JMS edition to dump the received message to console (note this uses QPid libraries):
./sdkperf_jmsamqp.sh -cip=amqp://localhost:5672 -stl=a/b/c
-md -q
curl http://localhost:9000/TOPIC/a/b/c -d 'hello' -H 'Content-Type: text'
^^^^^^^^^^^^^^^^^^ Start Message ^^^^^^^^^^^^^^^^^^^^^^^^^^^
JMSDeliveryMode: PERSISTENT
JMSDestination: a/b/c
JMSExpiration: 0
JMSPriority: 4
JMSTimestamp: 0
JMSRedelivered: false
JMSCorrelationID: null
JMSMessageID: null
JMSReplyTo: null
JMSType: null
JMSProperties: {JMSXDeliveryCount:1;}
Object Type: TextMessage
Text: len=5
hello
The header does not get mapped through, but does get used to set the message type. If I remove that HTTP header, the received AMQP message is binary. But since other types of Content-Types also map to TextMessages (e.g. application/json
, application/xml
, etc.), the fact you're receiving a TextMessage is not enough to infer exactly what Content-Type you published your REST message with.
For completeness, I used WireShark with an AMQP decoder, and you can see the header present on the received AMQP message:
Frame 3: 218 bytes on wire (1744 bits), 218 bytes captured (1744 bits) on interface \Device\NPF_Loopback, id 0
Null/Loopback
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 5672, Dst Port: 60662, Seq: 2, Ack: 1, Len: 174
Advanced Message Queueing Protocol
Length: 174
Doff: 2
Type: AMQP (0)
Channel: 2
Performative: transfer (20)
Arguments (5)
Message-Header
Durable: True
Message-Annotations (map of 1 element)
x-opt-jms-dest (byte): 1
Message-Properties
To: a/b/c
Content-Type: text <----------
Application-Properties (map of 1 element)
AaronEncoding (str8-utf8): CustomText
AMQP-Value (str32-utf8): hello
Set an additional custom header, a User Property, which will get passed through to the AMQP message:
curl http://localhost:9000/TOPIC/a/b/c -d 'hello' -H 'Solace-User-Property-AaronEncoding: CustomText' -H 'Content-Type: text'
JMSDestination: a/b/c
JMSProperties: {AaronEncoding:CustomText;JMSXDeliveryCount:1;}
Object Type: TextMessage
Text: len=5
hello
My always-goto guide for Solace REST interactions: https://docs.solace.com/API/RESTMessagingPrtl/Solace-REST-Message-Encoding.htm
Hope that helps!