Future Enhancements¶
Potential future enhancements that have been considered but not yet implemented. These are ideas for future development—not commitments or guarantees.
JMS-Compatible Systems (Low Effort)¶
These systems provide JMS client libraries that can be integrated with minimal effort since KETE already has a fully functional JMS-based destination (Amqp1Destination). The existing code uses standard jakarta.jms.* interfaces—only the ConnectionFactory implementation differs per system.
Why These Are Easy Wins
The current Amqp1Destination code is pure JMS. Adding these would only require:
- A new
*DestinationConfigclass with the system-specificConnectionFactory - Adding the client library dependency to
pom.xml(with shade relocation) - Documentation and quick-start examples
Amazon SQS via JMS (sqs-jms)¶
Amazon provides a JMS 2.0 client library for SQS, making integration straightforward.
Priority: 🥇 High (AWS market dominance)
Potential Configuration:
kete.routes.sqs.destination.kind=sqs-jms
kete.routes.sqs.destination.region=us-east-1
kete.routes.sqs.destination.queue=keycloak-events
# Optional for FIFO queues
kete.routes.sqs.destination.message-group-id=${realm}
# Authentication via environment variables or IAM role
ConnectionFactory:
import com.amazon.sqs.javamessaging.SQSConnectionFactory;
connectionFactory = new SQSConnectionFactory(
new ProviderConfiguration(),
SqsClient.builder().region(Region.of(region)).build()
);
Dependencies Required:
- com.amazonaws:amazon-sqs-java-messaging-lib
- software.amazon.awssdk:sqs
Authentication Options:
- Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
- IAM instance profile (EC2/ECS)
- IRSA (EKS)
- Web Identity Token
Apache Pulsar via JMS (pulsar-jms)¶
DataStax provides a JMS 2.0 client for Apache Pulsar.
Priority: 🥈 Medium (growing adoption)
Potential Configuration:
kete.routes.pulsar.destination.kind=pulsar-jms
kete.routes.pulsar.destination.service-url=pulsar://localhost:6650
kete.routes.pulsar.destination.topic=keycloak-events
kete.routes.pulsar.destination.namespace=public/default
ConnectionFactory:
import com.datastax.oss.pulsar.jms.PulsarConnectionFactory;
Map<String, Object> config = Map.of("brokerServiceUrl", serviceUrl);
connectionFactory = new PulsarConnectionFactory(config);
Dependencies Required:
- com.datastax.oss:pulsar-jms
IBM MQ (ibm-mq-jms)¶
IBM MQ has native JMS support—it's one of the original JMS implementations.
Priority: 🥉 Medium (enterprise legacy systems)
Potential Configuration:
kete.routes.ibm.destination.kind=ibm-mq-jms
kete.routes.ibm.destination.host=mq.example.com
kete.routes.ibm.destination.port=1414
kete.routes.ibm.destination.queue-manager=QM1
kete.routes.ibm.destination.channel=DEV.APP.SVRCONN
kete.routes.ibm.destination.queue=KEYCLOAK.EVENTS
kete.routes.ibm.destination.username=app
kete.routes.ibm.destination.password=secret
ConnectionFactory:
import com.ibm.mq.jms.MQConnectionFactory;
import com.ibm.msg.client.wmq.WMQConstants;
var factory = new MQConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setQueueManager(queueManager);
factory.setChannel(channel);
factory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
connectionFactory = factory;
Dependencies Required:
- com.ibm.mq:com.ibm.mq.allclient
ActiveMQ Classic (activemq-classic-jms)¶
Apache ActiveMQ "Classic" (5.x) uses OpenWire protocol with native JMS.
Priority: Low (most users should migrate to Artemis/AMQP 1.0)
Potential Configuration:
kete.routes.amq.destination.kind=activemq-classic-jms
kete.routes.amq.destination.broker-url=tcp://localhost:61616
kete.routes.amq.destination.queue=keycloak-events
kete.routes.amq.destination.username=admin
kete.routes.amq.destination.password=admin
ConnectionFactory:
import org.apache.activemq.ActiveMQConnectionFactory;
connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
Dependencies Required:
- org.apache.activemq:activemq-client
Note
ActiveMQ Artemis already works via AMQP 1.0 using the existing amqp-1 destination with Qpid JMS. This would only be needed for legacy OpenWire-only deployments.
Solace PubSub+ (solace-jms)¶
Solace provides a JMS API for their PubSub+ platform.
Priority: Low (niche enterprise)
Potential Configuration:
kete.routes.solace.destination.kind=solace-jms
kete.routes.solace.destination.host=solace.example.com
kete.routes.solace.destination.vpn=default
kete.routes.solace.destination.queue=keycloak-events
kete.routes.solace.destination.username=admin
kete.routes.solace.destination.password=admin
Dependencies Required:
- com.solacesystems:sol-jms
TIBCO EMS (tibco-ems-jms)¶
TIBCO Enterprise Message Service with native JMS.
Priority: Low (legacy enterprise)
Potential Configuration:
kete.routes.tibco.destination.kind=tibco-ems-jms
kete.routes.tibco.destination.server-url=tcp://localhost:7222
kete.routes.tibco.destination.queue=keycloak.events
kete.routes.tibco.destination.username=admin
kete.routes.tibco.destination.password=admin
Dependencies Required:
- com.tibco:tibjms (proprietary, not in Maven Central)
Protocol-Based Destinations (One Client, Many Brokers)¶
These destinations use open standard protocols, providing wide broker compatibility with a single client library—similar to how KETE's amqp-1 destination works with any AMQP 1.0 broker.
SignalR (signalr)¶
Stream events to Microsoft SignalR hubs for real-time web applications.
Priority: Medium (Microsoft ecosystem, ASP.NET applications)
Protocol: SignalR (WebSocket-based with fallbacks)
Compatible Systems:
| System | Notes |
|---|---|
| Azure SignalR Service | Managed SignalR in Azure |
| Self-hosted SignalR | ASP.NET Core apps |
| Blazor Server | Real-time Blazor applications |
Potential Configuration:
kete.routes.signalr.destination.kind=signalr
kete.routes.signalr.destination.hub-url=https://app.example.com/eventshub
kete.routes.signalr.destination.method=ReceiveKeycloakEvent
kete.routes.signalr.destination.access-token=...
Dependencies Required:
- com.microsoft.signalr:signalr (official Java client)
Use Cases: - Real-time dashboards showing login activity - Live user session monitoring - Browser-based admin consoles
Cloud Destinations (Native SDK Required)¶
Google Cloud Pub/Sub (gcp-pubsub)¶
Publish events to Google Cloud Pub/Sub topics.
Potential Configuration:
kete.routes.gcp.destination.kind=gcp-pubsub
kete.routes.gcp.destination.project-id=my-gcp-project
kete.routes.gcp.destination.topic=keycloak-events
kete.routes.gcp.destination.credentials-file=/path/to/service-account.json
# Or use GOOGLE_APPLICATION_CREDENTIALS environment variable
Dependencies Required:
- com.google.cloud:google-cloud-pubsub
Authentication Options: - Service account JSON key file - Workload Identity (GKE) - Application Default Credentials
AWS SNS (aws-sns)¶
Publish events to Amazon Simple Notification Service topics.
Potential Configuration:
kete.routes.aws.destination.kind=aws-sns
kete.routes.aws.destination.topic-arn=arn:aws:sns:us-east-1:123456789:keycloak-events
kete.routes.aws.destination.region=us-east-1
# Authentication via environment variables or IAM role
# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
Dependencies Required:
- software.amazon.awssdk:sns
Authentication Options: - Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) - IAM instance profile (EC2/ECS) - IRSA (EKS)
AWS SQS (aws-sqs)¶
Send events directly to Amazon Simple Queue Service queues.
Potential Configuration:
kete.routes.aws.destination.kind=aws-sqs
kete.routes.aws.destination.queue-url=https://sqs.us-east-1.amazonaws.com/123456789/keycloak-events
kete.routes.aws.destination.region=us-east-1
kete.routes.aws.destination.message-group-id=${realm} # For FIFO queues
Dependencies Required:
- software.amazon.awssdk:sqs
AWS Kinesis (aws-kinesis)¶
Stream events to Amazon Kinesis Data Streams for real-time analytics.
Potential Configuration:
kete.routes.aws.destination.kind=aws-kinesis
kete.routes.aws.destination.stream-name=keycloak-events
kete.routes.aws.destination.region=us-east-1
kete.routes.aws.destination.partition-key=${realm}
Dependencies Required:
- software.amazon.awssdk:kinesis
Database Destinations¶
JDBC Tables (jdbc-tables)¶
Persist events to database tables. Useful for audit logging and compliance.
Potential Configuration:
kete.routes.db.destination.kind=jdbc-tables
kete.routes.db.destination.jdbc.url=jdbc:postgresql://localhost:5432/events
kete.routes.db.destination.jdbc.username=events_user
kete.routes.db.destination.jdbc.password=secret
kete.routes.db.destination.jdbc.driver=org.postgresql.Driver
kete.routes.db.destination.table=keycloak_events
Supported Databases: - PostgreSQL - MySQL/MariaDB - SQL Server - Oracle - H2 (testing)
JDBC Stored Procedures (jdbc-callable)¶
Invoke stored procedures for custom event processing.
Potential Configuration:
kete.routes.sproc.destination.kind=jdbc-callable
kete.routes.sproc.destination.jdbc.url=jdbc:sqlserver://localhost:1433;databaseName=events
kete.routes.sproc.destination.jdbc.username=events_user
kete.routes.sproc.destination.jdbc.password=secret
kete.routes.sproc.destination.jdbc.procedure=CALL usp_ProcessKeycloakEvent(?, ?, ?, ?)
# Parameters: event_id, event_type, realm, payload
Redis Pub/Sub (redis-pubsub)¶
Publish events to Redis channels for real-time messaging.
Priority: 🥇 High (wide adoption, simple implementation)
Compatible Systems:
| System | Notes |
|---|---|
| Redis | Self-hosted, open-source |
| Redis Cloud | Managed Redis by Redis Inc. |
| Amazon ElastiCache | AWS managed Redis |
| Azure Cache for Redis | Azure managed Redis |
| Google Memorystore | GCP managed Redis |
| Upstash | Serverless Redis |
| KeyDB | Redis-compatible, multi-threaded |
| Dragonfly | Redis-compatible, high-performance |
Potential Configuration:
kete.routes.redis.destination.kind=redis-pubsub
kete.routes.redis.destination.host=redis.example.com
kete.routes.redis.destination.port=6379
kete.routes.redis.destination.channel=keycloak-events
kete.routes.redis.destination.password=secret
Dependencies Required:
- io.lettuce:lettuce-core or redis.clients:jedis
Redis Streams (redis-streams)¶
Append events to Redis Streams for persistent, ordered messaging.
Priority: 🥇 High (persistent messaging with consumer groups)
Compatible Systems: Same as Redis Pub/Sub above.
Potential Configuration:
kete.routes.redis.destination.kind=redis-streams
kete.routes.redis.destination.host=redis.example.com
kete.routes.redis.destination.port=6379
kete.routes.redis.destination.stream=keycloak-events
kete.routes.redis.destination.max-len=100000 # Trim to max entries
NATS (nats)¶
Publish events to NATS subjects for lightweight messaging.
Priority: 🥈 Medium (simple, fast, growing adoption)
Compatible Systems:
| System | Notes |
|---|---|
| NATS Server | Open-source, lightweight |
| NATS JetStream | Persistent streaming layer |
| Synadia Cloud | Managed NATS |
| Synadia NGS | Global NATS service |
Potential Configuration:
kete.routes.nats.destination.kind=nats
kete.routes.nats.destination.servers=nats://localhost:4222
kete.routes.nats.destination.subject=keycloak.events
kete.routes.nats.destination.username=user
kete.routes.nats.destination.password=secret
Dependencies Required:
- io.nats:jnats
NATS JetStream (nats-jetstream)¶
Publish events to NATS JetStream for persistent messaging with replay and consumer groups.
Priority: 🥈 Medium (persistent layer for NATS)
Potential Configuration:
kete.routes.nats.destination.kind=nats-jetstream
kete.routes.nats.destination.servers=nats://localhost:4222
kete.routes.nats.destination.stream=KEYCLOAK
kete.routes.nats.destination.subject=keycloak.events
Dependencies Required:
- io.nats:jnats
Apache Pulsar Native (pulsar-native)¶
Publish events to Apache Pulsar topics using the native Pulsar client (alternative to JMS wrapper).
Priority: 🥉 Low (JMS wrapper preferred, see pulsar-jms above)
Compatible Systems:
| System | Notes |
|---|---|
| Apache Pulsar | Self-hosted |
| StreamNative Cloud | Managed Pulsar |
| DataStax Astra Streaming | Managed Pulsar |
Potential Configuration:
kete.routes.pulsar.destination.kind=pulsar-native
kete.routes.pulsar.destination.service-url=pulsar://localhost:6650
kete.routes.pulsar.destination.topic=persistent://public/default/keycloak-events
kete.routes.pulsar.destination.auth-plugin=org.apache.pulsar.client.impl.auth.AuthenticationToken
kete.routes.pulsar.destination.auth-params=token:xxx
Dependencies Required:
- org.apache.pulsar:pulsar-client
Note
Consider using pulsar-jms instead (see JMS-Compatible Systems above) for simpler integration with existing KETE JMS infrastructure.
Additional Serializers¶
Avro (avro)¶
Serialize events using Apache Avro with Schema Registry support.
Potential Configuration:
kete.routes.avro.serializer.kind=avro
kete.routes.avro.serializer.schema-registry-url=http://schema-registry:8081
kete.routes.avro.serializer.auto-register-schemas=true
Dependencies Required:
- org.apache.avro:avro
- io.confluent:kafka-avro-serializer
Use Cases: - Kafka consumers requiring Avro format - Schema evolution and compatibility
Protocol Buffers (protobuf)¶
Serialize events using Google Protocol Buffers.
Potential Configuration:
kete.routes.proto.serializer.kind=protobuf
kete.routes.proto.serializer.schema-file=/path/to/event.proto
Dependencies Required:
- com.google.protobuf:protobuf-java
Use Cases: - gRPC-based consumers - Size-efficient binary format
Logging & Observability Destinations¶
Syslog (syslog)¶
Stream events to Syslog-compatible log aggregators using RFC 5424.
Priority: 🥇 High (wide enterprise adoption, low implementation effort)
Protocol: Syslog RFC 5424 over UDP/TCP/TLS
Compatible Systems:
| System | Notes |
|---|---|
| rsyslog | Linux default, high-performance |
| syslog-ng | Enterprise syslog with advanced routing |
| Graylog | Log management with syslog input |
| Splunk | Via syslog input or HEC |
| Elastic/Logstash | Via syslog input plugin |
| Papertrail | Managed cloud logging |
| Datadog | Log ingestion via syslog |
| Sumo Logic | Cloud SIEM with syslog |
| Loggly | Cloud log management |
| Fluentd/Fluent Bit | Via syslog input |
Potential Configuration:
kete.routes.syslog.destination.kind=syslog
kete.routes.syslog.destination.host=syslog.example.com
kete.routes.syslog.destination.port=514
kete.routes.syslog.destination.protocol=udp # udp, tcp, or tls
kete.routes.syslog.destination.facility=local0
kete.routes.syslog.destination.severity=info
kete.routes.syslog.destination.app-name=keycloak
Dependencies Required:
- com.cloudbees:syslog-java-client or custom RFC 5424 implementation
Why This Matters: - Nearly universal enterprise adoption - Simple protocol (text-based, like STOMP) - Integrates with existing log infrastructure - Low implementation effort
Real-Time Streaming Destinations¶
Server-Sent Events (sse)¶
Stream events to clients via HTTP Server-Sent Events.
Priority: 🥈 Medium (browser-friendly, simple implementation)
Protocol: SSE (HTTP streaming, text/event-stream)
Compatible Systems:
| System | Notes |
|---|---|
| Browsers | Native EventSource API |
| curl | curl -N for streaming |
| Real-time dashboards | React, Vue, Angular apps |
| API Gateways | Kong, AWS API Gateway |
| Mobile apps | iOS/Android SSE clients |
Potential Configuration:
kete.routes.sse.destination.kind=sse
kete.routes.sse.destination.url=http://dashboard.example.com/events
kete.routes.sse.destination.event-type=keycloak-event
kete.routes.sse.destination.retry=3000
Implementation Notes: - KETE acts as SSE publisher to an endpoint - Can be used with an SSE relay/fanout server - Simpler than WebSocket (unidirectional)
Use Cases: - Live admin dashboards - Real-time audit displays - Browser-based monitoring
gRPC Streaming (grpc)¶
Stream events to gRPC servers using bidirectional or server streaming.
Priority: 🥉 Low (high effort, niche use case)
Protocol: gRPC over HTTP/2
Compatible Systems:
| System | Notes |
|---|---|
| Custom gRPC servers | Any language with gRPC support |
| Envoy Proxy | gRPC routing and load balancing |
| Google Cloud Run | Serverless gRPC |
| Kubernetes services | Native gRPC support |
| Istio | Service mesh with gRPC |
Potential Configuration:
kete.routes.grpc.destination.kind=grpc
kete.routes.grpc.destination.target=grpc-server.example.com:9090
kete.routes.grpc.destination.service=keycloak.EventService
kete.routes.grpc.destination.method=StreamEvents
kete.routes.grpc.destination.tls.enabled=true
Dependencies Required:
- io.grpc:grpc-netty-shaded
- io.grpc:grpc-protobuf
- io.grpc:grpc-stub
- Protobuf schema for events
Implementation Notes:
- Requires defining a .proto schema for Keycloak events
- Higher complexity than HTTP/WebSocket
- Best for microservices architectures already using gRPC
Notes¶
These enhancements are ideas for future development based on common use cases. Implementation priority depends on:
- Community demand
- Contributor availability
- Complexity vs. value
- Existing workarounds (e.g., Azure Service Bus works via AMQP 1.0)
Implementation Strategy¶
JMS-Compatible Systems are the easiest to add because:
- KETE's
Amqp1Destinationalready uses pure JMS code (jakarta.jms.*) - Only the
ConnectionFactoryinstantiation differs per system - All JMS message handling, session management, and resource cleanup is reusable
- Could be refactored into a base
JmsDestinationclass if multiple JMS systems are added
Native SDK Destinations require more effort because:
- Each cloud provider has unique SDK patterns
- Authentication mechanisms vary significantly
- No code reuse between implementations
Some destinations may never be implemented if the existing destinations provide adequate coverage through protocol compatibility (e.g., ActiveMQ Artemis via AMQP 1.0).