From f646773b68e3c3635d389301918428771107715d Mon Sep 17 00:00:00 2001 From: Peridot Date: Mon, 17 Jul 2023 20:36:12 +0200 Subject: [PATCH] Create throwing handler --- .../org/panda_lang/utilities/inject/Bind.java | 8 ++ .../utilities/inject/DefaultBind.java | 6 ++ .../utilities/inject/HandledBindValue.java | 11 ++- .../utilities/inject/InjectorProcessor.java | 17 ++-- .../inject/DependencyInjectionFieldsTest.java | 4 +- .../DependencyInjectionHandlerTest.java | 78 +++++++++++++++++++ .../DependencyInjectionInstancesTest.java | 4 +- .../inject/DependencyInjectionWikiTest.java | 2 +- 8 files changed, 113 insertions(+), 17 deletions(-) create mode 100644 di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionHandlerTest.java diff --git a/di/src/main/java/org/panda_lang/utilities/inject/Bind.java b/di/src/main/java/org/panda_lang/utilities/inject/Bind.java index 0e05e8d..274cdc5 100644 --- a/di/src/main/java/org/panda_lang/utilities/inject/Bind.java +++ b/di/src/main/java/org/panda_lang/utilities/inject/Bind.java @@ -17,6 +17,7 @@ package org.panda_lang.utilities.inject; import org.jetbrains.annotations.NotNull; +import panda.std.function.ThrowingTriFunction; import panda.std.function.TriFunction; import java.lang.annotation.Annotation; import java.util.function.Supplier; @@ -44,6 +45,13 @@ public interface Bind extends Comparable> { */ void assignHandler(TriFunction handler); + /** + * Assign custom handler to the bind which can throw an exception + * + * @param handler the handler which accepts type of parameter and bind type as arguments + */ + void assignThrowingHandler(ThrowingTriFunction handler); + /** * Get the value of bind for the required (parameter) type and instance of a bind type * diff --git a/di/src/main/java/org/panda_lang/utilities/inject/DefaultBind.java b/di/src/main/java/org/panda_lang/utilities/inject/DefaultBind.java index 8b19674..0b460ab 100644 --- a/di/src/main/java/org/panda_lang/utilities/inject/DefaultBind.java +++ b/di/src/main/java/org/panda_lang/utilities/inject/DefaultBind.java @@ -16,6 +16,7 @@ package org.panda_lang.utilities.inject; +import panda.std.function.ThrowingTriFunction; import panda.std.function.TriFunction; import panda.utilities.ObjectUtils; import java.lang.annotation.Annotation; @@ -59,6 +60,11 @@ public void assignHandler(TriFunction handler) { with(new HandledBindValue<>(handler)); } + @Override + public void assignThrowingHandler(ThrowingTriFunction handler) { + with(new HandledBindValue<>(handler)); + } + @Override public Object getValue(Property required, A annotation, Object... injectedArgs) throws Exception { return this.value.getValue(required, annotation, injectedArgs); diff --git a/di/src/main/java/org/panda_lang/utilities/inject/HandledBindValue.java b/di/src/main/java/org/panda_lang/utilities/inject/HandledBindValue.java index 2892677..97d3e10 100644 --- a/di/src/main/java/org/panda_lang/utilities/inject/HandledBindValue.java +++ b/di/src/main/java/org/panda_lang/utilities/inject/HandledBindValue.java @@ -16,19 +16,24 @@ package org.panda_lang.utilities.inject; +import panda.std.function.ThrowingTriFunction; import panda.std.function.TriFunction; import java.lang.annotation.Annotation; final class HandledBindValue implements BindValue { - private final TriFunction handler; + private final ThrowingTriFunction handler; - HandledBindValue(TriFunction handler) { + HandledBindValue(ThrowingTriFunction handler) { this.handler = handler; } + HandledBindValue(TriFunction handler) { + this.handler = handler::apply; + } + @Override - public Object getValue(Property required, A annotation, Object... injectorArgs) { + public Object getValue(Property required, A annotation, Object... injectorArgs) throws Exception { return handler.apply(required, annotation, injectorArgs); } diff --git a/di/src/main/java/org/panda_lang/utilities/inject/InjectorProcessor.java b/di/src/main/java/org/panda_lang/utilities/inject/InjectorProcessor.java index b8d7e6b..c574f0b 100644 --- a/di/src/main/java/org/panda_lang/utilities/inject/InjectorProcessor.java +++ b/di/src/main/java/org/panda_lang/utilities/inject/InjectorProcessor.java @@ -43,13 +43,7 @@ final class InjectorProcessor { this.injector = injector; this.autoConstructBind = new DefaultBind<>(AutoConstruct.class); - this.autoConstructBind.assignHandler((property, annotation, injectorArgs) -> { - try { - return injector.newInstanceWithFields(property.getType(), injectorArgs); - } catch (Exception ex) { - throw new DependencyInjectionException(ex); - } - }); + this.autoConstructBind.assignThrowingHandler((property, annotation, injectorArgs) -> injector.newInstanceWithFields(property.getType(), injectorArgs)); } protected Object[] fetchValues(InjectorCache cache, Object... injectorArgs) throws Exception { @@ -170,8 +164,13 @@ protected Bind[] fetchBinds(Annotation[] annotations, Executable exe } protected Bind fetchBind(@Nullable Annotation annotation, Property property) throws MissingBindException { - Class requiredType = annotation != null ? annotation.annotationType() : property.getType(); - Bind bind = this.injector.getResources().getBind(requiredType).orNull(); + Bind bind = annotation != null + ? this.injector.getResources().getBind(annotation.annotationType()).orNull() + : null; + + if (bind == null) { + bind = this.injector.getResources().getBind(property.getType()).orNull(); + } if (bind == null && property.getAnnotation(AutoConstruct.class) != null) { bind = this.autoConstructBind; } diff --git a/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionFieldsTest.java b/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionFieldsTest.java index 451a32b..6cf031c 100644 --- a/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionFieldsTest.java +++ b/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionFieldsTest.java @@ -58,7 +58,7 @@ public String serveAbstract() { } @Test - void shouldInjectFields() throws Throwable { + void shouldInjectFields() { Injector injector = DependencyInjection.createInjector(resources -> { resources.on(boolean.class).assignInstance(true); resources.on(String.class).assignInstance("Hello Field"); @@ -68,7 +68,7 @@ void shouldInjectFields() throws Throwable { resources.annotatedWithTested(Custom.class).assignHandler((property, custom, objects) -> objects[0].toString()); }); - Service service = injector.forFields(Service.class).newInstance("custom argument"); + Service service = injector.newInstanceWithFields(Service.class,"custom argument"); assertEquals("Hello Field 7", service.serve()); assertEquals("1.2 254623242914889729", service.serveAbstract()); } diff --git a/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionHandlerTest.java b/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionHandlerTest.java new file mode 100644 index 0000000..b37481e --- /dev/null +++ b/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionHandlerTest.java @@ -0,0 +1,78 @@ +package org.panda_lang.utilities.inject; + +import org.junit.jupiter.api.Test; +import org.panda_lang.utilities.inject.annotations.Inject; +import org.panda_lang.utilities.inject.annotations.Injectable; +import org.panda_lang.utilities.inject.annotations.PostConstruct; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.concurrent.ThreadLocalRandom; + +import static org.junit.jupiter.api.Assertions.*; + +public class DependencyInjectionHandlerTest { + + @Injectable + @Retention(RetentionPolicy.RUNTIME) + @interface Custom { + } + + @Injectable + @Retention(RetentionPolicy.RUNTIME) + @interface AwesomeRandom { + } + + public static class Service1 { + @Inject + @Custom + public String fieldOne; + + @Inject + public int fieldTwo; + + @Inject + @AwesomeRandom + public int fieldThree; + + @PostConstruct + public void construct() { + assertEquals("HelloWorld", this.fieldOne); + + assertEquals(7, this.fieldTwo); + assertTrue(this.fieldTwo >= 2 && this.fieldTwo <= 10); + } + } + + @Test + void shouldCreateInstance() { + Injector injector = DependencyInjection.createInjector(resources -> { + resources.annotatedWith(Custom.class).assignHandler((type, annotation, args) -> "HelloWorld"); + resources.on(int.class).assignHandler((type, annotation, args) -> { + AwesomeRandom randomAnnotation = type.getAnnotation(AwesomeRandom.class); + if (randomAnnotation == null) { + return 7; + } + return ThreadLocalRandom.current().nextInt(2, 10); + }); + }); + + injector.newInstanceWithFields(Service1.class); + } + + public static class Service2 { + @Inject + public String fieldOne; + } + + @Test + void shouldNotCreateInstance() { + Injector injector = DependencyInjection.createInjector(resources -> { + resources.on(String.class).assignThrowingHandler((type, annotation, args) -> { + throw new Exception("Failed"); + }); + }); + assertThrows(DependencyInjectionException.class, () -> injector.newInstanceWithFields(Service2.class)); + } + +} diff --git a/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionInstancesTest.java b/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionInstancesTest.java index baafd14..f68033f 100644 --- a/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionInstancesTest.java +++ b/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionInstancesTest.java @@ -7,7 +7,7 @@ final class DependencyInjectionInstancesTest { @Test - void shouldInjectInstances() throws Throwable { + void shouldInjectInstances() { Injector injector = DependencyInjection.createInjector(); // some logic, a few hours later... @@ -15,7 +15,7 @@ void shouldInjectInstances() throws Throwable { injector.getResources().on(Custom.class).assignInstance(new CustomImpl()); // singleton injector.getResources().on(Bean.class).assignInstance(Bean::new); // new instance per call - Service service = injector.forConstructor(Service.class).newInstance(); + Service service = injector.newInstance(Service.class); assertNotNull(service); } diff --git a/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionWikiTest.java b/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionWikiTest.java index 46230da..8fd2364 100644 --- a/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionWikiTest.java +++ b/di/src/test/java/org/panda_lang/utilities/inject/DependencyInjectionWikiTest.java @@ -27,7 +27,7 @@ final class DependencyInjectionWikiTest { @Test - void testWikiExample() throws Throwable { + void testWikiExample() { Injector injector = DependencyInjection.createInjector(resources -> { resources.annotatedWith(AwesomeRandom.class).assignHandler((required, annotation, injectorArgs) -> { Class expectedType = required.getType();