Note: an update of this article has been posted here.
This article shows how Delphi can use IP multicast to find Apache ActiveMQ message brokers in the local network.
With the code below, a Delphi application can list all ActiveMQ brokers, see their status, and get their IP address. This allows for dynamic configuration of client applications (built for example with Habari Client for ActiveMQ), where systems do not need to know the location of message brokers. It also allows automatic handling of broker failures or maintenance windows without intervention.
Example output
The output shows that a broker was found, running on the computer ‘my-PC’. The URL part indicates that the broker provides a connector for the OpenWire protocol on port 61616.
Waiting for broker discovery messages ... Brokers found: default.ActiveMQ-4.alive.%localhost%tcp://my-PC:61616
Source code
The solution below is based on the Internet Direct (Indy) component TIdIPMCastClient. It declares a subclass (TActiveMQDiscovery), configured for the ActiveMQ default settings. The application uses an instance of this specialiced class to listen for multicast messages for the duration of 2.5 seconds. During this time, it collects the messages in a string list. Finally, it displays the list of found brokers and terminates.
program DiscoverMulticast;
{$APPTYPE CONSOLE}
uses
IdIPMCastClient, IdGlobal, IdSocketHandle,
Classes, SysUtils;
type
TActiveMQDiscovery = class(TIdIPMCastClient)
private
FBrokers: TStrings;
public
constructor Create;
destructor Destroy; override;
procedure MyIPMCastRead(Sender: TObject;
const AData: TIdBytes; ABinding: TIdSocketHandle);
property Brokers: TStrings read FBrokers;
end;
{ TActiveMQDiscovery }
constructor TActiveMQDiscovery.Create;
begin
inherited Create(nil);
DefaultPort := 6155;
MulticastGroup := '239.255.2.3';
OnIPMCastRead := MyIPMCastRead;
FBrokers := TStringList.Create;
end;
destructor TActiveMQDiscovery.Destroy;
begin
Brokers.Free;
inherited;
end;
procedure TActiveMQDiscovery.MyIPMCastRead(Sender: TObject;
const AData: TIdBytes; ABinding: TIdSocketHandle);
var
S: string;
begin
S := StringOf(AData);
if Brokers.IndexOf(S) = -1 then
begin
Brokers.Add(S);
end;
end;
// run the demo ----------------------------------------------------
procedure Main;
var
MC: TActiveMQDiscovery;
begin
MC := TActiveMQDiscovery.Create;
try
MC.ReuseSocket := rsTrue;
MC.ThreadedEvent := True;
try
MC.Active := True;
WriteLn('Waiting for broker discovery messages ...');
Sleep(2500);
if MC.Brokers.Count = 0 then
begin
WriteLn('No brokers found');
end
else
begin
WriteLn('Brokers found:');
Writeln(MC.Brokers.Text);
end;
WriteLn('Hint any key to continue');
Readln;
except
on E: Exception do
begin
WriteLn(E.Message);
ReadLn;
end;
end;
finally
MC.Free;
end;
end;
begin
Main;
end.