# Elixir STOMP Client
A custom STOMP protocol client implementation for Elixir that provides precise control over message formatting, especially content-length headers. Features automatic reconnection, heartbeat support, and callback-based message handling.
## Features
- **Custom Message Formatting**: Control over content-length headers (can omit content-length like Go's NoContentLength)
- **Automatic Reconnection**: Automatic reconnection with configurable retry intervals
- **Heartbeat Support**: Built-in heartbeat mechanism to keep connections alive
- **Callback-based Handling**: Process-based callback system for handling connection events and messages
- **STOMP 1.2 Compatible**: Full support for STOMP 1.2 protocol
- **Subscription Management**: Easy subscription and unsubscription management
## Installation
Add `elixir_stomp_client` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:elixir_stomp_client, "~> 0.1.0"}
]
end
```
## Usage
### Basic Connection
```elixir
# Define a callback handler process
defmodule MyStompHandler do
use GenServer
def start_link(_) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
def init(_) do
{:ok, %{}}
end
def handle_info({:stomp_client, :on_connect, frame}, state) do
IO.puts("Connected to STOMP server!")
{:noreply, state}
end
def handle_info({:stomp_client, :on_message, message}, state) do
IO.puts("Received message: #{inspect(message)}")
{:noreply, state}
end
def handle_info({:stomp_client, :on_disconnect, _}, state) do
IO.puts("Disconnected from STOMP server")
{:noreply, state}
end
def handle_info({:stomp_client, :on_connect_error, error}, state) do
IO.puts("Connection error: #{inspect(error)}")
{:noreply, state}
end
end
# Start the handler
{:ok, _} = MyStompHandler.start_link(nil)
# Connect to STOMP server
{:ok, client} = StompClient.connect([
host: "localhost",
port: 61613,
username: "guest",
password: "guest"
], callback_handler: MyStompHandler)
```
### Sending Messages
```elixir
# Send a simple message
StompClient.send(client, "/queue/test", "Hello World!")
# Send a message with custom headers
StompClient.send(client, "/queue/test", "Hello World!", [
{"custom-header", "custom-value"}
])
```
### Subscribing to Destinations
```elixir
# Subscribe to a queue
StompClient.subscribe(client, "/queue/test")
# Subscribe with a selector
StompClient.subscribe(client, "/queue/test", selector: "priority > 5")
# Subscribe with custom ID
StompClient.subscribe(client, "/queue/test", id: "my-subscription")
```
### Unsubscribing
```elixir
StompClient.unsubscribe(client, "/queue/test")
```
### Disconnecting
```elixir
StompClient.disconnect(client)
```
## Configuration Options
When connecting, you can provide the following options:
- `host` - STOMP server hostname (required)
- `port` - STOMP server port (default: 61613)
- `username` or `login` - Authentication username
- `password` or `passcode` - Authentication password
- `callback_handler` - Process to receive callback messages (required)
## Callback Messages
Your callback handler will receive the following messages:
- `{:stomp_client, :on_connect, frame}` - When successfully connected
- `{:stomp_client, :on_message, message}` - When a message is received
- `{:stomp_client, :on_disconnect, nil}` - When disconnected
- `{:stomp_client, :on_connect_error, error}` - When connection fails
- `{:stomp_client, :on_send, frame}` - When a frame is sent (optional)
## Message Structure
Received messages have the following structure:
```elixir
%{
"destination" => "/queue/test",
"body" => "message content",
# ... other STOMP headers
}
```
## Advanced Usage
### Custom Frame Building
The client provides two frame building methods:
1. **Standard frames** (with content-length): Used for CONNECT, SUBSCRIBE, etc.
2. **Frames without content-length**: Used for SEND messages (configurable)
This allows compatibility with different STOMP server implementations that may have different content-length requirements.
### Heartbeat Configuration
The client automatically sends heartbeats every 25 seconds when connected. The server heartbeat timeout is set to 30 seconds.
### Error Handling
The client includes robust error handling with automatic reconnection. Connection failures trigger reconnection attempts every 5 seconds.
## License
MIT License. See LICENSE file for details.
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Submit a pull request