Extension system for loading and managing service discovery implementations with support for multiple discovery methods and configuration-based selection. The Discovery extension integrates with Akka's extension system to provide a singleton service discovery manager per ActorSystem.
The main extension class that manages service discovery implementations and provides access to the default configured discovery method.
/**
* Discovery extension for managing service discovery implementations
* Integrates with Akka's extension system as a singleton per ActorSystem
*/
final class Discovery extends Extension {
/**
* Get the default ServiceDiscovery implementation
* Configured via akka.discovery.method in application.conf
* @return ServiceDiscovery instance
* @throws IllegalArgumentException if no default method is configured
*/
def discovery: ServiceDiscovery
/**
* Load a specific ServiceDiscovery implementation by method name
* Implementation classes are configured via akka.discovery.[method].class
* Instances are cached - subsequent calls with same method return same instance
* @param method Discovery method name (e.g., "akka-dns", "config", "aggregate")
* @return ServiceDiscovery instance for the specified method
* @throws IllegalArgumentException if method is not properly configured
*/
def loadServiceDiscovery(method: String): ServiceDiscovery
}Usage Examples:
import akka.actor.ActorSystem
import akka.discovery.Discovery
implicit val system = ActorSystem("my-system")
// Get default discovery implementation (from akka.discovery.method config)
val defaultDiscovery = Discovery(system).discovery
// Load specific discovery implementations
val dnsDiscovery = Discovery(system).loadServiceDiscovery("akka-dns")
val configDiscovery = Discovery(system).loadServiceDiscovery("config")
val aggregateDiscovery = Discovery(system).loadServiceDiscovery("aggregate")
// Use different implementations for different purposes
val webServices = dnsDiscovery.lookup("web-service", 3.seconds)
val localServices = configDiscovery.lookup("local-service", 1.second)The companion object implementing Akka's ExtensionId pattern for integration with the actor system extension mechanism.
/**
* Extension ID and provider for Discovery extension
* Implements Akka's extension pattern for singleton per ActorSystem
*/
object Discovery extends ExtensionId[Discovery] with ExtensionIdProvider {
/**
* Get Discovery extension instance for ActorSystem
* @param system ActorSystem instance
* @return Discovery extension singleton for this system
*/
def apply(system: ActorSystem): Discovery
/**
* Alternative way to get Discovery extension instance
* @param system ActorSystem instance
* @return Discovery extension singleton for this system
*/
def get(system: ActorSystem): Discovery
/**
* Get Discovery extension from ClassicActorSystemProvider
* @param system ClassicActorSystemProvider instance
* @return Discovery extension singleton for this system
*/
def get(system: ClassicActorSystemProvider): Discovery
/**
* Extension lookup method (part of ExtensionIdProvider)
* @return This Discovery extension ID
*/
def lookup: Discovery.type
/**
* Create new Discovery extension instance (part of ExtensionId)
* @param system ExtendedActorSystem instance
* @return New Discovery extension instance
*/
def createExtension(system: ExtendedActorSystem): Discovery
}Usage Examples:
import akka.actor.{ActorSystem, ClassicActorSystemProvider}
import akka.discovery.Discovery
// Standard ActorSystem
val system = ActorSystem("my-system")
val discovery1 = Discovery(system)
val discovery2 = Discovery.get(system)
// discovery1 and discovery2 are the same instance
// From ClassicActorSystemProvider
val provider: ClassicActorSystemProvider = system
val discovery3 = Discovery.get(provider)The Discovery extension relies on configuration in application.conf to determine which implementations to load:
akka.discovery {
# Default discovery method - must be set to a valid method name
method = "akka-dns" # or "config", "aggregate", or custom implementation
}akka.discovery {
# DNS-based discovery (built-in)
akka-dns {
class = "akka.discovery.dns.DnsServiceDiscovery"
}
# Configuration-based discovery (built-in)
config {
class = "akka.discovery.config.ConfigServiceDiscovery"
services-path = "akka.discovery.config.services"
}
# Aggregate discovery (built-in)
aggregate {
class = "akka.discovery.aggregate.AggregateServiceDiscovery"
discovery-methods = ["akka-dns", "config"]
}
# Custom implementation example
my-custom {
class = "com.example.MyServiceDiscovery"
# custom configuration properties...
}
}The extension supports loading these built-in discovery methods:
Configuration Examples:
// application.conf configuration affects Discovery behavior
import akka.actor.ActorSystem
import akka.discovery.Discovery
// With akka.discovery.method = "akka-dns"
val system1 = ActorSystem("dns-system")
val dnsDiscovery = Discovery(system1).discovery
// Returns DNS-based discovery implementation
// With akka.discovery.method = "aggregate"
val system2 = ActorSystem("aggregate-system")
val aggregateDiscovery = Discovery(system2).discovery
// Returns aggregate discovery that tries multiple methods
// Load specific methods regardless of default
val specificDns = Discovery(system1).loadServiceDiscovery("akka-dns")
val specificConfig = Discovery(system1).loadServiceDiscovery("config")import akka.discovery.Discovery
try {
// Will throw IllegalArgumentException if method not configured
val invalidDiscovery = Discovery(system).loadServiceDiscovery("non-existent")
} catch {
case _: IllegalArgumentException =>
println("Discovery method not properly configured")
}
try {
// Will throw IllegalArgumentException if akka.discovery.method = "<method>" (placeholder)
val defaultDiscovery = Discovery(system).discovery
} catch {
case e: IllegalArgumentException if e.getMessage.contains("No default service discovery") =>
println("Default discovery method not configured - set akka.discovery.method")
case e: IllegalArgumentException if e.getMessage.contains("Illegal") =>
println("Discovery implementation class incompatible or missing constructor")
}