Skip to content

Commit 24cc9c3

Browse files
authored
When Services.set() is called with io.helidon.config.Config, also set the instances for common config. (helidon-io#10473)
This is a temporary solution until we have this available as part of service registry functionality (as we need to avoid reflection to analyze the contract).
1 parent 549454d commit 24cc9c3

1 file changed

Lines changed: 52 additions & 40 deletions

File tree

service/registry/src/main/java/io/helidon/service/registry/CoreServiceRegistry.java

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
* Basic implementation of the service registry with simple dependency support.
5050
*/
5151
class CoreServiceRegistry implements ServiceRegistry, Scopes {
52+
private static final ResolvedType COMMON_CONFIG = ResolvedType.create("io.helidon.common.config.Config");
53+
private static final ResolvedType CONFIG = ResolvedType.create("io.helidon.config.Config");
5254
private static final AtomicInteger COUNTER = new AtomicInteger();
5355

5456
private final String id = String.valueOf(COUNTER.incrementAndGet());
@@ -549,53 +551,63 @@ <T> void set(Class<T> contract, T[] instances) {
549551
stateWriteLock.lock();
550552
try {
551553
ResolvedType contractType = ResolvedType.create(contract);
552-
checkValidContract(contractType);
553-
ServiceInfo serviceInfo = servicesByType.get(contractType.type());
554-
if (serviceInfo == null) {
555-
Set<ServiceInfo> serviceInfos = new TreeSet<>(SERVICE_INFO_COMPARATOR);
556-
557-
// we need to keep order of the instances; if somebody calls set, and then add, it may be tricky
558-
double currentWeight = Weighted.DEFAULT_WEIGHT;
559-
for (T instance : instances) {
560-
// each instance will have its own descriptor
561-
VirtualDescriptor vt = new VirtualDescriptor(contractType.type(), currentWeight, instance);
562-
ServiceProvider<Object> provider = new ServiceProvider<>(this,
563-
vt);
564-
Activator<Object> activator = Activators.create(provider, instance);
565-
566-
servicesByDescriptor.put(vt, new ServiceManager<>(this,
567-
scopeSupplier(vt),
568-
provider,
569-
true,
570-
() -> activator));
571-
serviceInfos.add(vt);
572-
// reduce by a small number, so other things behave as expected
573-
currentWeight -= 0.001;
574-
}
575-
// replace the instances
576-
servicesByContract.put(contractType, serviceInfos);
554+
if (contractType.equals(CONFIG)) {
555+
// this is a temporary solution to our problem of two config interfaces, we want users to only set it once
556+
doSet(CONFIG, instances);
557+
doSet(COMMON_CONFIG, instances);
577558
} else {
578-
// this is a service instance, not contract implementation (i.e. the contract is actual service class)
579-
ServiceProvider<Object> provider = new ServiceProvider<>(this,
580-
(ServiceDescriptor<Object>) serviceInfo);
581-
if (instances.length != 1) {
582-
throw new ServiceRegistryException("Attempting to set a service provider with wrong number of instances. "
583-
+ "A service provider must have exactly one instance.");
584-
}
585-
Activator<Object> activator = Activators.create(provider, instances[0]);
586-
servicesByDescriptor.put(serviceInfo, new ServiceManager<>(this,
587-
scopeSupplier(serviceInfo),
588-
provider,
589-
true,
590-
() -> activator));
559+
doSet(contractType, instances);
591560
}
592-
// reset bindings, as build-time binding would ignore instances explicitly set
593-
bindings.forgetContract(contractType);
594561
} finally {
595562
stateWriteLock.unlock();
596563
}
597564
}
598565

566+
private <T> void doSet(ResolvedType contractType, T[] instances) {
567+
checkValidContract(contractType);
568+
ServiceInfo serviceInfo = servicesByType.get(contractType.type());
569+
if (serviceInfo == null) {
570+
Set<ServiceInfo> serviceInfos = new TreeSet<>(SERVICE_INFO_COMPARATOR);
571+
572+
// we need to keep order of the instances; if somebody calls set, and then add, it may be tricky
573+
double currentWeight = Weighted.DEFAULT_WEIGHT;
574+
for (T instance : instances) {
575+
// each instance will have its own descriptor
576+
VirtualDescriptor vt = new VirtualDescriptor(contractType.type(), currentWeight, instance);
577+
ServiceProvider<Object> provider = new ServiceProvider<>(this,
578+
vt);
579+
Activator<Object> activator = Activators.create(provider, instance);
580+
581+
servicesByDescriptor.put(vt, new ServiceManager<>(this,
582+
scopeSupplier(vt),
583+
provider,
584+
true,
585+
() -> activator));
586+
serviceInfos.add(vt);
587+
// reduce by a small number, so other things behave as expected
588+
currentWeight -= 0.001;
589+
}
590+
// replace the instances
591+
servicesByContract.put(contractType, serviceInfos);
592+
} else {
593+
// this is a service instance, not contract implementation (i.e. the contract is actual service class)
594+
ServiceProvider<Object> provider = new ServiceProvider<>(this,
595+
(ServiceDescriptor<Object>) serviceInfo);
596+
if (instances.length != 1) {
597+
throw new ServiceRegistryException("Attempting to set a service provider with wrong number of instances. "
598+
+ "A service provider must have exactly one instance.");
599+
}
600+
Activator<Object> activator = Activators.create(provider, instances[0]);
601+
servicesByDescriptor.put(serviceInfo, new ServiceManager<>(this,
602+
scopeSupplier(serviceInfo),
603+
provider,
604+
true,
605+
() -> activator));
606+
}
607+
// reset bindings, as build-time binding would ignore instances explicitly set
608+
bindings.forgetContract(contractType);
609+
}
610+
599611
InterceptionMetadata interceptionMetadata() {
600612
return interceptionMetadata;
601613
}

0 commit comments

Comments
 (0)