Skip to content

Commit cfc8e6f

Browse files
feat: improve handling of default values for ValueInjectionPoints (#4620)
* feat: improve handling of default values for ValueInjectionPoints * rename method, add javadoc
1 parent 90362c9 commit cfc8e6f

File tree

15 files changed

+102
-47
lines changed

15 files changed

+102
-47
lines changed

core/common/boot/src/main/java/org/eclipse/edc/boot/system/DependencyGraph.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public List<InjectionContainer<ServiceExtension>> of(List<ServiceExtension> exte
121121

122122
var defaultServiceProvider = defaultServiceProviders.get(injectionPoint.getType());
123123
if (defaultServiceProvider != null) {
124-
injectionPoint.setDefaultServiceProvider(defaultServiceProvider);
124+
injectionPoint.setDefaultValueProvider(defaultServiceProvider);
125125
}
126126
})
127127
.forEach(injectionPoint -> container.getInjectionPoints().add(injectionPoint));

core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ConfigurationInjectionPoint.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414

1515
package org.eclipse.edc.boot.system.injection;
1616

17-
import org.eclipse.edc.boot.system.injection.lifecycle.ServiceProvider;
1817
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
1918
import org.eclipse.edc.spi.result.AbstractResult;
2019
import org.eclipse.edc.spi.result.Result;
2120
import org.eclipse.edc.spi.system.ServiceExtensionContext;
21+
import org.eclipse.edc.spi.system.ValueProvider;
2222
import org.jetbrains.annotations.NotNull;
23+
import org.jetbrains.annotations.Nullable;
2324

2425
import java.lang.reflect.Constructor;
2526
import java.lang.reflect.Field;
@@ -88,15 +89,15 @@ public Result<Void> setTargetValue(Object value) {
8889
* Not used here, will always return null
8990
*/
9091
@Override
91-
public ServiceProvider getDefaultServiceProvider() {
92+
public @Nullable ValueProvider getDefaultValueProvider() {
9293
return null;
9394
}
9495

9596
/**
9697
* Not used here
9798
*/
9899
@Override
99-
public void setDefaultServiceProvider(ServiceProvider defaultServiceProvider) {
100+
public void setDefaultValueProvider(ValueProvider defaultValueProvider) {
100101

101102
}
102103

@@ -182,7 +183,7 @@ private Predicate<Constructor<?>> constructorFilter(List<FieldValue> args) {
182183
private @NotNull List<FieldValue> resolveSettingsFields(ServiceExtensionContext context, Field[] fields) {
183184
return injectionPointsFrom(fields)
184185
.map(ip -> {
185-
var val = ip.resolve(context, null /*the default supplier arg is not used anyway*/);
186+
var val = ip.resolve(context, new InjectionPointDefaultServiceSupplier());
186187
var fieldName = ip.getTargetField().getName();
187188
return new FieldValue(fieldName, val);
188189
})

core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionPoint.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414

1515
package org.eclipse.edc.boot.system.injection;
1616

17-
import org.eclipse.edc.boot.system.injection.lifecycle.ServiceProvider;
1817
import org.eclipse.edc.spi.result.Result;
1918
import org.eclipse.edc.spi.system.ServiceExtensionContext;
19+
import org.eclipse.edc.spi.system.ValueProvider;
2020
import org.jetbrains.annotations.Nullable;
2121

2222
import java.util.List;
@@ -57,22 +57,23 @@ public interface InjectionPoint<T> {
5757
*
5858
* @return the default service provider if any, null otherwise
5959
*/
60-
@Nullable ServiceProvider getDefaultServiceProvider();
60+
@Nullable ValueProvider getDefaultValueProvider();
6161

6262
/**
6363
* Sets the default service provider.
6464
*
65-
* @param defaultServiceProvider the default service provider
65+
* @param defaultValueProvider the default service provider
6666
*/
67-
void setDefaultServiceProvider(ServiceProvider defaultServiceProvider);
67+
void setDefaultValueProvider(ValueProvider defaultValueProvider);
6868

6969
/**
7070
* Resolves the value for an injected field from either the context or a default service supplier. For some injection points,
7171
* this may also return a (statically declared) default value.
7272
*
7373
* @param context The {@link ServiceExtensionContext} from which the value is resolved.
74-
* @param defaultServiceSupplier Some service dynamically resolve a default value in case the actual value isn't found on the context.
75-
* @return The resolved value, or null if the injected field is not required..
74+
* @param defaultServiceSupplier Provider for default values that can be resolved statically (e.g. through an annotation attribute) or
75+
* dynamically (e.g. by instantiating an object or resolving from context).
76+
* @return The resolved value, or null if the injected field is not required.
7677
* @throws EdcInjectionException in case the value could not be resolved
7778
*/
7879
Object resolve(ServiceExtensionContext context, DefaultServiceSupplier defaultServiceSupplier);

core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionPointDefaultServiceSupplier.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.eclipse.edc.spi.system.ServiceExtensionContext;
1818
import org.jetbrains.annotations.Nullable;
1919

20+
import static java.util.Optional.ofNullable;
21+
2022
/**
2123
* Supplies the default {@link org.eclipse.edc.boot.system.injection.lifecycle.ServiceProvider} that has been stored in
2224
* the {@link InjectionPoint}
@@ -25,11 +27,11 @@ public class InjectionPointDefaultServiceSupplier implements DefaultServiceSuppl
2527

2628
@Override
2729
public @Nullable Object provideFor(InjectionPoint<?> injectionPoint, ServiceExtensionContext context) {
28-
var defaultService = injectionPoint.getDefaultServiceProvider();
30+
var defaultService = injectionPoint.getDefaultValueProvider();
2931
if (injectionPoint.isRequired() && defaultService == null) {
3032
throw new EdcInjectionException("No default provider for required service " + injectionPoint.getType());
3133
}
32-
return defaultService == null ? null : defaultService.register(context);
34+
return ofNullable(defaultService).map(vp -> vp.get(context)).orElse(null);
3335
}
3436

3537
}

core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ServiceInjectionPoint.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414

1515
package org.eclipse.edc.boot.system.injection;
1616

17-
import org.eclipse.edc.boot.system.injection.lifecycle.ServiceProvider;
1817
import org.eclipse.edc.spi.result.Result;
1918
import org.eclipse.edc.spi.system.ServiceExtension;
2019
import org.eclipse.edc.spi.system.ServiceExtensionContext;
20+
import org.eclipse.edc.spi.system.ValueProvider;
21+
import org.jetbrains.annotations.Nullable;
2122

2223
import java.lang.reflect.Field;
2324
import java.util.List;
@@ -36,7 +37,7 @@ public class ServiceInjectionPoint<T> implements InjectionPoint<T> {
3637
private final T instance;
3738
private final Field injectedField;
3839
private final boolean isRequired;
39-
private ServiceProvider defaultServiceProvider;
40+
private ValueProvider defaultServiceProvider;
4041

4142
public ServiceInjectionPoint(T instance, Field injectedField) {
4243
this(instance, injectedField, true);
@@ -75,13 +76,13 @@ public Result<Void> setTargetValue(Object value) {
7576
}
7677

7778
@Override
78-
public ServiceProvider getDefaultServiceProvider() {
79+
public @Nullable ValueProvider getDefaultValueProvider() {
7980
return defaultServiceProvider;
8081
}
8182

8283
@Override
83-
public void setDefaultServiceProvider(ServiceProvider defaultServiceProvider) {
84-
this.defaultServiceProvider = defaultServiceProvider;
84+
public void setDefaultValueProvider(ValueProvider defaultValueProvider) {
85+
this.defaultServiceProvider = defaultValueProvider;
8586

8687
}
8788

core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ValueInjectionPoint.java

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,18 @@
1414

1515
package org.eclipse.edc.boot.system.injection;
1616

17-
import org.eclipse.edc.boot.system.injection.lifecycle.ServiceProvider;
1817
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
1918
import org.eclipse.edc.spi.result.Result;
2019
import org.eclipse.edc.spi.system.ServiceExtensionContext;
20+
import org.eclipse.edc.spi.system.ValueProvider;
21+
import org.jetbrains.annotations.Nullable;
2122

2223
import java.lang.reflect.Field;
2324
import java.util.List;
2425
import java.util.Map;
2526

27+
import static java.util.Optional.ofNullable;
28+
2629
/**
2730
* Injection point for configuration values ("settings"). Configuration values must be basic data types and be annotated
2831
* with {@link Setting}, for example:
@@ -94,22 +97,25 @@ public Result<Void> setTargetValue(Object value) {
9497
}
9598

9699
/**
97-
* Not used here, always returns null;
100+
* Returns a {@link ValueProvider} that takes the annotation's {@link Setting#defaultValue()} attribute or null
98101
*
99-
* @return always {@code null}
102+
* @return a nullable default value provider
100103
*/
101104
@Override
102-
public ServiceProvider getDefaultServiceProvider() {
105+
public @Nullable ValueProvider getDefaultValueProvider() {
106+
if (!Setting.NULL.equals(annotationValue.defaultValue())) {
107+
return context -> annotationValue.defaultValue();
108+
}
103109
return null;
104110
}
105111

106112
/**
107113
* Not used here
108114
*
109-
* @param defaultServiceProvider Ignored
115+
* @param defaultValueProvider Ignored
110116
*/
111117
@Override
112-
public void setDefaultServiceProvider(ServiceProvider defaultServiceProvider) {
118+
public void setDefaultValueProvider(ValueProvider defaultValueProvider) {
113119

114120
}
115121

@@ -125,15 +131,20 @@ public Object resolve(ServiceExtensionContext context, DefaultServiceSupplier de
125131
}
126132

127133
// not found in config, but there is a default value
128-
var def = annotationValue.defaultValue();
129-
if (def != null && !def.trim().equals(Setting.NULL)) {
130-
var msg = "Config value: no setting found for '%s', falling back to default value '%s'".formatted(key, def);
131-
if (annotationValue.warnOnMissingConfig()) {
132-
context.getMonitor().warning(msg);
133-
} else {
134-
context.getMonitor().debug(msg);
134+
var def = ofNullable(defaultServiceSupplier)
135+
.map(s -> s.provideFor(this, context))
136+
.map(Object::toString);
137+
if (def.isPresent()) {
138+
var defaultValue = def.get();
139+
if (!defaultValue.trim().equals(Setting.NULL)) {
140+
var msg = "Config value: no setting found for '%s', falling back to default value '%s'".formatted(key, defaultValue);
141+
if (annotationValue.warnOnMissingConfig()) {
142+
context.getMonitor().warning(msg);
143+
} else {
144+
context.getMonitor().debug(msg);
145+
}
146+
return parseEntry(defaultValue, type);
135147
}
136-
return parseEntry(def, type);
137148
}
138149

139150
// neither in config, nor default val

core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/lifecycle/ExtensionLifecycleManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public static void bootServiceExtensions(List<InjectionContainer<ServiceExtensio
5555

5656
var serviceProviders = container.getServiceProviders();
5757
if (serviceProviders != null) {
58-
serviceProviders.forEach(serviceProvider -> serviceProvider.register(context));
58+
serviceProviders.forEach(serviceProvider -> serviceProvider.get(context));
5959
}
6060
}
6161

core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/lifecycle/ServiceProvider.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,27 @@
1818
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
1919
import org.eclipse.edc.spi.system.ServiceExtension;
2020
import org.eclipse.edc.spi.system.ServiceExtensionContext;
21+
import org.eclipse.edc.spi.system.ValueProvider;
2122

2223
/**
2324
* Represent a service provider, that's a method annotated with the {@link Provider}
2425
*
25-
* @param method the provider method.
26+
* @param method the provider method.
2627
* @param extension the extension in which the method is contained.
2728
*/
28-
public record ServiceProvider(ProviderMethod method, ServiceExtension extension) {
29+
public record ServiceProvider(ProviderMethod method, ServiceExtension extension) implements ValueProvider {
2930

3031
/**
3132
* Call the method and register the service.
3233
*
3334
* @param context the service context.
3435
* @return the instantiated service.
3536
*/
36-
public Object register(ServiceExtensionContext context) {
37+
@Override
38+
public Object get(ServiceExtensionContext context) {
3739
var type = method.getReturnType();
3840
var service = method.invoke(extension, context);
3941
context.registerService(type, service);
4042
return service;
4143
}
42-
4344
}

core/common/boot/src/test/java/org/eclipse/edc/boot/system/injection/ConfigurationInjectionPointTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ void setTargetValue() throws IllegalAccessException {
5757
}
5858

5959
@Test
60-
void getDefaultServiceProvider() {
61-
assertThat(injectionPoint.getDefaultServiceProvider()).isNull();
60+
void getDefaultValueProvider() {
61+
assertThat(injectionPoint.getDefaultValueProvider()).isNull();
6262
}
6363

6464
@Test
65-
void setDefaultServiceProvider() {
65+
void setDefaultValueProvider() {
6666
//noop
6767
}
6868

core/common/boot/src/test/java/org/eclipse/edc/boot/system/injection/InjectionPointDefaultServiceSupplierTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ class InjectionPointDefaultServiceSupplierTest {
3232
void shouldRegisterDefaultService() {
3333
var injectionPoint = new ServiceInjectionPoint<>("any", mock());
3434
ServiceProvider serviceProvider = mock();
35-
when(serviceProvider.register(any())).thenReturn("service");
36-
injectionPoint.setDefaultServiceProvider(serviceProvider);
35+
when(serviceProvider.get(any())).thenReturn("service");
36+
injectionPoint.setDefaultValueProvider(serviceProvider);
3737
ServiceExtensionContext context = mock();
3838

3939
var service = supplier.provideFor(injectionPoint, context);

0 commit comments

Comments
 (0)