Multiple Implementations of the Same Service in OSGi
One of the most common questions when working with OSGi services is:
What if more than one bundle provides an implementation of the same service interface?
In traditional Java or even Spring-based applications, this often leads to ambiguity errors or requires manual configuration.
In OSGi, however, multiple implementations are not an edge case - they are a core feature.
Let’s break down how OSGi handles this cleanly and dynamically.
The Scenario
Assume we have a common service interface:
public interface PaymentService {
void pay();
}
Now imagine multiple bundles provide implementations:
@Component(service = PaymentService.class)
public class PaypalPaymentService implements PaymentService {
public void pay() {
System.out.println("PayPal payment");
}
}
@Component(service = PaymentService.class)
public class CardPaymentService implements PaymentService {
public void pay() {
System.out.println("Card payment");
}
}
Both services are:
Registered in the Service Registry
Available at the same time
Dynamically manageable
So… which one gets injected?
1. Default Behavior: One Is Chosen (Non-deterministic)
If you write:
@Reference
private PaymentService paymentService;
OSGi will:
Pick one matching service
Selection is not guaranteed unless you guide it
This is usually not recommended
2. Service Ranking: Prefer One Implementation
OSGi allows services to declare a ranking:
@Component(
service = PaymentService.class,
property = "service.ranking=100"
)
public class PaypalPaymentService implements PaymentService {}
@Component(
service = PaymentService.class,
property = "service.ranking=10"
)
public class CardPaymentService implements PaymentService {}
- Higher service.ranking wins
- DS automatically injects the highest-ranked service
This is useful when:
You have a default implementation
Others act as fallbacks
3. Filter-Based Injection: Select Explicitly
You can select a service using properties:
@Component(
service = PaymentService.class,
property = "type=paypal"
)
public class PaypalPaymentService {}
@Component(
service = PaymentService.class,
property = "type=card"
)
public class CardPaymentService {}
@Reference(target = "(type=paypal)")
private PaymentService paymentService;
This gives precise control over which service is injected.
4. Inject All Implementations (Preferred for Extensibility)
OSGi allows multiple services to be injected at once:
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC
)
private List<PaymentService> paymentServices;
This is powerful because:
Services can be added or removed at runtime
The list updates automatically
No restart required
Perfect for:
Plugin systems
Strategy patterns
Dynamic extensions
5. Optional References
If a service is optional:
@Reference(
cardinality = ReferenceCardinality.OPTIONAL,
policy = ReferencePolicy.DYNAMIC
)
private PaymentService paymentService;
The component:
Activates even if no service is present
Gets updated when one appears later

