allModulesDefined() {
+ return Stream.of(
+ Arguments.of(Named.of("In working order A", new AvajeModule[]{
+ new ModAModule(),
+ new ModCModule(),
+ new ModBModule(),
+ new CrossCutModule(),
+ new ModDModule(),
+ new ModEModule(),
+ new ManyModule(),
+ })),
+ Arguments.of(Named.of("In alphabetical order", new AvajeModule[]{
+ new CrossCutModule(),
+ new ManyModule(),
+ new ModAModule(),
+ new ModBModule(),
+ new ModCModule(),
+ new ModDModule(),
+ new ModEModule(),
+ })),
+ Arguments.of(Named.of("In reverse alphabetical order", new AvajeModule[]{
+ new ModEModule(),
+ new ModDModule(),
+ new ModCModule(),
+ new ModBModule(),
+ new ModAModule(),
+ new ManyModule(),
+ new CrossCutModule(),
+ })),
+ Arguments.of(Named.of("In shuffled order", new AvajeModule[]{
+ new ModEModule(),
+ new ModBModule(),
+ new ModDModule(),
+ new ManyModule(),
+ new ModCModule(),
+ new ModAModule(),
+ new CrossCutModule(),
+ })),
+ Arguments.of(Named.of("Only the end module is required", new AvajeModule[]{
+ new ManyModule()
+ }))
+ );
+ }
- try (BeanScope beanScope = BeanScope.builder()
-// .modules(new CrossCutModule())
- .build()) {
+ private static final Class[] CHECKABLE = {
+ BeanCross.class,
+ BeanCross2.class,
+ BeanCross3.class,
+ BeanInMany.class,
+ BeanInModA.class,
+ BeanInModB.class,
+ BOther.class,
+ BeanInModC.class,
+ COther.class,
+ BeanInModD.class,
+ BeanInModE.class
+ };
-// var beanInModB = beanScope.get(BeanInModB.class);
-// assertThat(beanInModB).isNotNull();
- }
+ @ParameterizedTest(name = "Multi Scope Test: {1}")
+ @MethodSource("allModulesDefined")
+ void bootstrap(AvajeModule... modules) {
+ try (BeanScope beanScope = assertDoesNotThrow(() -> BeanScope.builder().modules(modules).build())) {
+ for (final Class> clazz : CHECKABLE) {
+ assertTrue(beanScope.getOptional(clazz).isPresent(), "Bean not found: " + clazz.getSimpleName());
+ }
+ }
}
}
diff --git a/inject/src/main/java/io/avaje/inject/InjectModule.java b/inject/src/main/java/io/avaje/inject/InjectModule.java
index a1e31af3..f773ad7d 100644
--- a/inject/src/main/java/io/avaje/inject/InjectModule.java
+++ b/inject/src/main/java/io/avaje/inject/InjectModule.java
@@ -105,6 +105,22 @@
*/
Class>[] requiresPackages() default {};
+ /**
+ * Modules and scopes that are expected to be automatically imported when this module is requested manually
+ *
+ * Like {@code requires}, references to beans created in the imported module/scope are not treated as missing.
+ * Unlike {@code requires} though, referenced items will be provided automatically.
+ *
+ * Any item that a referenced module/scope {@code requires} must either:
+ *
+ * - Be provided by another {@code automaticallyImport}ed item
+ * - Be required by this module as well
+ *
+ *
+ * Circular dependencies are not permitted
+ */
+ Class>[] automaticallyImport() default {};
+
/**
* Internal use only - identifies the custom scope annotation associated to this module.
*