STOMP (RabbitMQ)
STOMP 1.2 client tuned for RabbitMQ — exchange destinations, queue conventions and RabbitMQ-specific headers.
STOMP 1.2 client tuned for RabbitMQ — exchange destinations, queue conventions and RabbitMQ-specific headers.
This is the Client Protocol STOMP Component for RabbitMQ Broker.
TsgcWSPClient_STOMP_RabbitMQ| Standards & specs | STOMP 1.2 specification · RabbitMQ — STOMP plugin |
| Component class | TsgcWSPClient_STOMP_RabbitMQ (unit sgcWebSocket_Protocols, ancestor TsgcWSProtocol_STOMP_RabbitMQ_Client in unit sgcWebSocket_Protocol_STOMP_RabbitMQ_Client) |
| Frameworks | VCL, FireMonkey, Lazarus / FPC, .NET |
| Platforms | Windows, macOS, Linux, iOS, Android |
The principal published / public properties used to configure and drive the component. Consult the online help for the full list.
Authentication | Sends login and passcode headers in the STOMP CONNECT frame to authenticate the client against the RabbitMQ Web-STOMP plugin. |
Client | References the TsgcWebSocketClient that carries STOMP frames to RabbitMQ's Web-STOMP plugin on port 15674. |
Broker | References a TsgcWSSTOMPBroker component so the STOMP protocol runs over raw TCP against RabbitMQ instead of the Web-STOMP plugin. |
Options | Extra STOMP-level settings sent in the CONNECT frame, such as the RabbitMQ virtual host used to select the broker logical namespace. |
HeartBeat | Negotiates the STOMP 1.1/1.2 heart-beat header so the client and RabbitMQ exchange keep-alive newlines and detect silent drops. |
Versions | Selects which STOMP wire versions (1.0, 1.1, 1.2) are offered to RabbitMQ in the WebSocket subprotocol list and the CONNECT accept-version header. |
Guid | Unique identifier that binds this STOMP RabbitMQ subprotocol instance to its WebSocket or broker connection. |
Version | Read-only string with the sgcWebSockets build version of the STOMP RabbitMQ subprotocol component. |
The principal public methods exposed by the component.
Disconnect() | Sends a DISCONNECT frame and closes the STOMP session with the RabbitMQ broker. |
SubscribeTopic() | Subscribes to a RabbitMQ topic using the /topic/name destination prefix. |
UnSubscribeTopic() | Cancels a previous topic subscription registered with SubscribeTopic. |
PublishTopic() | Publishes a message to a RabbitMQ topic using the /topic/name destination prefix. |
SubscribeQueue() | Subscribes to a shared queue auto-declared by the STOMP gateway using the /queue/name prefix. |
UnSubscribeQueue() | Cancels a previous subscription registered with SubscribeQueue. |
PublishQueue() | Publishes a message to a gateway-managed queue using the /queue/name prefix. |
SubscribeQueueOutside() | Subscribes to a queue already declared outside STOMP (e.g. via AMQP) using the /amq/queue/name prefix. |
UnSubscribeQueueOutside() | Cancels a previous subscription registered with SubscribeQueueOutside. |
PublishQueueOutside() | Publishes a message to an externally declared queue using the /amq/queue/name prefix. |
The component exposes the following published events; consult the online help for full event-handler signatures.
OnRabbitMQConnected | TsgcWSPClient_STOMP_RabbitMQ › Events › OnRabbitMQConnected |
OnRabbitMQDisconnected | TsgcWSPClient_STOMP_RabbitMQ › Events › OnRabbitMQDisconnected |
OnRabbitMQError | Fires when an ERROR frame is received from the RabbitMQ broker; delivers the error message and the full ERROR Headers. |
OnRabbitMQMessage | TsgcWSPClient_STOMP_RabbitMQ › Events › OnRabbitMQMessage |
OnRabbitMQPing | Fires when a heart-beat (single newline) is exchanged with the RabbitMQ broker; reports direction and timestamps of the last exchange. |
OnRabbitMQReceipt | TsgcWSPClient_STOMP_RabbitMQ › Events › OnRabbitMQReceipt |
Drop the component on a form, configure the properties below and activate it. The snippet that follows shows the typical Connect to the RabbitMQ Web-STOMP plugin configuration.
oClient := TsgcWebSocketClient.Create(nil); oClient.Host := 'rabbit.example.com'; oClient.Port := 15674; oClient.Options.Parameters := '/ws'; oRabbitMQ := TsgcWSPClient_STOMP_RabbitMQ.Create(nil); oRabbitMQ.Client := oClient; oRabbitMQ.Authentication.Enabled := True; oRabbitMQ.Authentication.UserName := 'guest'; oRabbitMQ.Authentication.Password := 'guest'; oRabbitMQ.Options.VirtualHost := '/'; // HeartBeat values are milliseconds oRabbitMQ.HeartBeat.Enabled := True; oRabbitMQ.HeartBeat.Outgoing := 10000; oRabbitMQ.HeartBeat.Incoming := 10000; oRabbitMQ.OnRabbitMQConnected := OnRabbitMQConnectedEvent; oRabbitMQ.OnRabbitMQMessage := OnRabbitMQMessageEvent; oClient.Active := True;
oClient = new TsgcWebSocketClient(this); oClient->Host = "rabbit.example.com"; oClient->Port = 15674; oClient->Options->Parameters = "/ws"; oRabbitMQ = new TsgcWSPClient_STOMP_RabbitMQ(this); oRabbitMQ->Client = oClient; oRabbitMQ->Authentication->Enabled = true; oRabbitMQ->Authentication->UserName = "guest"; oRabbitMQ->Authentication->Password = "guest"; oRabbitMQ->Options->VirtualHost = "/"; oRabbitMQ->HeartBeat->Enabled = true; oRabbitMQ->HeartBeat->Outgoing = 10000; oRabbitMQ->HeartBeat->Incoming = 10000; oRabbitMQ->OnRabbitMQConnected = OnRabbitMQConnectedEvent; oRabbitMQ->OnRabbitMQMessage = OnRabbitMQMessageEvent; oClient->Active = true;
// the .NET client exposes the flat OnSTOMP* events for every STOMP broker oClient = new TsgcWebSocketClient(); oClient.Host = "rabbit.example.com"; oClient.Port = 15674; oClient.Options.Parameters = "/ws"; oRabbitMQ = new TsgcWSPClient_STOMP_RabbitMQ(); oRabbitMQ.Client = oClient; oRabbitMQ.Authentication.Enabled = true; oRabbitMQ.Authentication.UserName = "guest"; oRabbitMQ.Authentication.Password = "guest"; oRabbitMQ.Options.VirtualHost = "/"; oRabbitMQ.HeartBeat.Enabled = true; oRabbitMQ.HeartBeat.Outgoing = 10000; oRabbitMQ.HeartBeat.Incoming = 10000; oRabbitMQ.OnSTOMPConnected += OnSTOMPConnectedEvent; oRabbitMQ.OnSTOMPMessage += OnSTOMPMessageEvent; oClient.Active = true;
Each scenario shows the configuration and method calls needed to drive the component through a specific real-world flow. Every identifier below is taken from the component declaration shipped with the library.
SubscribeTopic and PublishTopic use the /topic/name destination prefix, SubscribeQueue and PublishQueue use /queue/name, the queue being declared by the STOMP gateway. Subscribe once the CONNECTED frame has arrived, that is, inside the OnRabbitMQConnected handler.
procedure TForm1.OnRabbitMQConnectedEvent(Connection: TsgcWSConnection; Headers: TsgcWSRabbitMQSTOMPHeadersConnected); begin oRabbitMQ.SubscribeTopic('quotes'); oRabbitMQ.SubscribeQueue('orders'); oRabbitMQ.PublishTopic('quotes', 'AAPL 195.30'); oRabbitMQ.PublishQueue('orders', '{"orderId": 12345}'); end; procedure TForm1.OnRabbitMQMessageEvent(Connection: TsgcWSConnection; MessageText: String; Headers: TsgcWSRabbitMQSTOMPHeadersMessage; Subscription: TsgcWSBrokerSTOMPSubscriptionItem); begin DoLog(Headers.Destination + ': ' + MessageText); end;
void __fastcall TForm1::OnRabbitMQConnectedEvent(TsgcWSConnection *Connection, TsgcWSRabbitMQSTOMPHeadersConnected *Headers) { oRabbitMQ->SubscribeTopic("quotes"); oRabbitMQ->SubscribeQueue("orders"); oRabbitMQ->PublishTopic("quotes", "AAPL 195.30"); oRabbitMQ->PublishQueue("orders", "{\"orderId\": 12345}"); } void __fastcall TForm1::OnRabbitMQMessageEvent(TsgcWSConnection *Connection, String MessageText, TsgcWSRabbitMQSTOMPHeadersMessage *Headers, TsgcWSBrokerSTOMPSubscriptionItem *Subscription) { DoLog(Headers->Destination + ": " + MessageText); }
void OnSTOMPConnectedEvent(TsgcWSConnection Connection, string Version, string Server, string Session, string HeartBeat, string RawHeaders) { oRabbitMQ.SubscribeTopic("quotes"); oRabbitMQ.SubscribeQueue("orders"); oRabbitMQ.PublishTopic("quotes", "AAPL 195.30"); oRabbitMQ.PublishQueue("orders", "{\"orderId\": 12345}"); } void OnSTOMPMessageEvent(TsgcWSConnection Connection, string MessageText, string Destination, string MessageId, string Subscription, string ACK, string ContentType, string RawHeaders) { DoLog(Destination + ": " + MessageText); }
SubscribeQueueOutside and PublishQueueOutside address a queue that was declared through AMQP or the management UI, using the /amq/queue/name prefix. SubscribeExchange binds a pattern on an exchange, and PublishExchange sends to a routing key. Queue arguments such as message TTL or a dead-letter exchange are set through the Queue property.
oRabbitMQ.Queue.MessageTTL := 60000; oRabbitMQ.Queue.MaxLength := 1000; oRabbitMQ.Queue.DeadLetterExchange := 'dlx'; // queue declared outside the STOMP gateway: /amq/queue/invoices oRabbitMQ.SubscribeQueueOutside('invoices'); oRabbitMQ.PublishQueueOutside('invoices', 'INV-2026-001'); // exchange binding: SUBSCRIBE to a pattern, SEND to a routing key oRabbitMQ.SubscribeExchange('logs', 'app.*'); oRabbitMQ.PublishExchange('logs', 'app.error', 'disk full');
oRabbitMQ->Queue->MessageTTL = 60000; oRabbitMQ->Queue->MaxLength = 1000; oRabbitMQ->Queue->DeadLetterExchange = "dlx"; oRabbitMQ->SubscribeQueueOutside("invoices"); oRabbitMQ->PublishQueueOutside("invoices", "INV-2026-001"); oRabbitMQ->SubscribeExchange("logs", "app.*"); oRabbitMQ->PublishExchange("logs", "app.error", "disk full");
oRabbitMQ.Queue.MessageTTL = 60000; oRabbitMQ.Queue.MaxLength = 1000; oRabbitMQ.Queue.DeadLetterExchange = "dlx"; oRabbitMQ.SubscribeQueueOutside("invoices"); oRabbitMQ.PublishQueueOutside("invoices", "INV-2026-001"); oRabbitMQ.SubscribeExchange("logs", "app.*"); oRabbitMQ.PublishExchange("logs", "app.error", "disk full");
Broker_Options.Acknowledgments decides who sends the ACK frame. Leave it at ackAutomatic and the component acknowledges every message for you, switch it to ackManual and you call ACK or ACKEx yourself from the message handler. BeginTransaction, CommitTransaction and AbortTransaction group SEND and ACK frames into one atomic unit.
// take over the acknowledgement, and subscribe requesting client ACK oRabbitMQ.Broker_Options.Acknowledgments := ackManual; oRabbitMQ.SubscribeQueue('orders', True, False, False, ackIndividual); procedure TForm1.OnRabbitMQMessageEvent(Connection: TsgcWSConnection; MessageText: String; Headers: TsgcWSRabbitMQSTOMPHeadersMessage; Subscription: TsgcWSBrokerSTOMPSubscriptionItem); begin // STOMP 1.2 uses the ack header, 1.1 and 1.0 the message-id header if Headers.ACK <> '' then oRabbitMQ.ACKEx(Headers.ACK, Subscription.Id) else oRabbitMQ.ACKEx(Headers.MessageId, Subscription.Id); end; // atomic group of SEND frames oRabbitMQ.BeginTransaction('tx-1'); oRabbitMQ.PublishQueue('orders', 'first', 'text/plain', 'tx-1'); oRabbitMQ.PublishQueue('orders', 'second', 'text/plain', 'tx-1'); oRabbitMQ.CommitTransaction('tx-1');
oRabbitMQ->Broker_Options->Acknowledgments = ackManual; oRabbitMQ->SubscribeQueue("orders", true, false, false, ackIndividual); void __fastcall TForm1::OnRabbitMQMessageEvent(TsgcWSConnection *Connection, String MessageText, TsgcWSRabbitMQSTOMPHeadersMessage *Headers, TsgcWSBrokerSTOMPSubscriptionItem *Subscription) { if (Headers->ACK != "") oRabbitMQ->ACKEx(Headers->ACK, Subscription->Id); else oRabbitMQ->ACKEx(Headers->MessageId, Subscription->Id); } oRabbitMQ->BeginTransaction("tx-1"); oRabbitMQ->PublishQueue("orders", "first", "text/plain", "tx-1"); oRabbitMQ->PublishQueue("orders", "second", "text/plain", "tx-1"); oRabbitMQ->CommitTransaction("tx-1");
// 0 = auto, 1 = client (multiple), 2 = client-individual oRabbitMQ.BrokerOptions.Acknowledgments = TsgcWSBrokerACK.Manual; oRabbitMQ.SubscribeQueue("orders", true, false, false, 2); void OnSTOMPMessageEvent(TsgcWSConnection Connection, string MessageText, string Destination, string MessageId, string Subscription, string ACK, string ContentType, string RawHeaders) { oRabbitMQ.ACK(ACK != "" ? ACK : MessageId); }
Every external claim links back to a primary source. The online-help references decode the canonical deep-link the company maintains for this component.