From 5a0e9be2346462722c3150ae3779b63108b3de40 Mon Sep 17 00:00:00 2001 From: Reed von Redwitz Date: Fri, 1 May 2026 11:15:10 +0200 Subject: [PATCH] feat(spawn-application): uptake DI binding API improvements --- .../AbstractTemplatedLauncher.java | 56 +++++-------------- .../AbstractTemplatedPlatform.java | 4 +- 2 files changed, 15 insertions(+), 45 deletions(-) diff --git a/spawn-application/src/main/java/build/spawn/application/AbstractTemplatedLauncher.java b/spawn-application/src/main/java/build/spawn/application/AbstractTemplatedLauncher.java index dbd2e61..87daaf2 100644 --- a/spawn-application/src/main/java/build/spawn/application/AbstractTemplatedLauncher.java +++ b/spawn-application/src/main/java/build/spawn/application/AbstractTemplatedLauncher.java @@ -23,7 +23,6 @@ import build.base.commandline.CommandLine; import build.base.configuration.Configuration; import build.base.configuration.ConfigurationBuilder; -import build.base.foundation.Introspection; import build.base.logging.Logger; import build.base.naming.UniqueNameGenerator; import build.base.option.TemporaryDirectory; @@ -34,7 +33,6 @@ import build.base.table.option.RowComparator; import build.base.table.option.TableName; import build.codemodel.foundation.usage.GenericTypeUsage; -import build.codemodel.foundation.usage.NamedTypeUsage; import build.codemodel.injection.Binding; import build.codemodel.injection.Context; import build.codemodel.injection.Dependency; @@ -52,6 +50,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -243,10 +242,7 @@ public A launch(final P platform, // allow the process interfaces to be used for injection launchContext.bind((Class) process.getClass()).to(process); - - Introspection.getAll(process.getClass(), Class::getInterfaces) - .filter(i -> !i.equals(Addressable.class)) - .forEach(i -> launchContext.bind((Class) i).to(process)); + launchContext.bind(process).asAllInterfaces(i -> !i.equals(Addressable.class)); // instantiate individual facets final Set> facets = launchOptions.stream(Facet.class) @@ -254,57 +250,33 @@ public A launch(final P platform, .map(facet -> { final Object implementation = facet.getFactory().apply(launchContext); - // allow injection of facets + // allow injection of facets individually and as Iterable launchContext.bind((Class) facet.getInterface()).to(implementation); + launchContext.bindSet((Class) facet.getInterface()).add(implementation); // create a synthetic Facet that always resolves to the same implementation return Facet.of(facet.getInterface(), _ -> facet.getInterface().cast(implementation)); }) .collect(Collectors.toSet()); - // allow Iterable to be resolved for injection where T is implemented by zero or more Facets. + // fallback: return an empty Iterable for any T not populated via bindSet above launchContext.addResolver(new Resolver>() { @Override public Optional>> resolve(final Dependency dependency) { - if (dependency.typeUsage() instanceof GenericTypeUsage genericTypeUsage && genericTypeUsage.typeName().canonicalName().equals(Iterable.class.getCanonicalName()) && genericTypeUsage.parameters().count() == 1) { - - final var parameterTypeUsage = genericTypeUsage.parameters() - .findFirst() - .orElseThrow(); - - if (parameterTypeUsage instanceof NamedTypeUsage namedTypeUsage) { - try { - final var parameterClass = this.getClass() - .getClassLoader() - .loadClass(namedTypeUsage.typeName().canonicalName()); - - // find the Facets that implement T - final var list = facets.stream() - .map(facet -> parameterClass.cast(facet.getFactory().apply(launchContext))) - .filter(parameterClass::isInstance) - .toList(); - - return Optional.of(new ValueBinding>() { - @Override - @SuppressWarnings("unchecked") - public Iterable value() { - return (Iterable) list; - } - - @Override - public Dependency dependency() { - return dependency; - } - }); + return Optional.of(new ValueBinding>() { + @Override + public Iterable value() { + return List.of(); } - catch (final ClassNotFoundException e) { - LOGGER.debug("Could not load class [{0}] for Iterable injection resolution", - namedTypeUsage.typeName().canonicalName(), e); + + @Override + public Dependency dependency() { + return dependency; } - } + }); } return Optional.empty(); diff --git a/spawn-application/src/main/java/build/spawn/application/AbstractTemplatedPlatform.java b/spawn-application/src/main/java/build/spawn/application/AbstractTemplatedPlatform.java index e750178..ac34706 100644 --- a/spawn-application/src/main/java/build/spawn/application/AbstractTemplatedPlatform.java +++ b/spawn-application/src/main/java/build/spawn/application/AbstractTemplatedPlatform.java @@ -172,7 +172,6 @@ public Configuration configuration() { } @Override - @SuppressWarnings({"unchecked", "rawtypes"}) public Context createContext(final Class applicationClass, final Configuration configuration) { @@ -189,8 +188,7 @@ public Context createContext(final Class applicationClass context.bind(InjectionFramework.class).to(this.injectionFramework); // allow all interfaces of the Platform to be injected - Introspection.getAll(getClass(), Class::getInterfaces) - .forEach(i -> context.bind((Class) i).to(this)); + context.bind(this).asAllInterfaces(); // allows the Platform Server to be injected context.bind(Server.class).to(this.server);