...})` to inform the avaje processor that these beans are provided at runtime.
+
diff --git a/modules/jooby-avaje-inject/pom.xml b/modules/jooby-avaje-inject/pom.xml
new file mode 100644
index 0000000000..f5f9e84144
--- /dev/null
+++ b/modules/jooby-avaje-inject/pom.xml
@@ -0,0 +1,54 @@
+
+
+
+
+ io.jooby
+ modules
+ 3.1.0-SNAPSHOT
+
+
+ 4.0.0
+ jooby-avaje-inject
+
+
+
+ io.jooby
+ jooby
+ ${jooby.version}
+
+
+
+
+ io.avaje
+ avaje-inject
+
+
+
+ io.avaje
+ avaje-inject-generator
+ provided
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+
+ org.jacoco
+ org.jacoco.agent
+ runtime
+ test
+
+
+
diff --git a/modules/jooby-avaje-inject/src/main/java/io/jooby/avaje/inject/AvajeInjectModule.java b/modules/jooby-avaje-inject/src/main/java/io/jooby/avaje/inject/AvajeInjectModule.java
new file mode 100644
index 0000000000..7ac6f62a3f
--- /dev/null
+++ b/modules/jooby-avaje-inject/src/main/java/io/jooby/avaje/inject/AvajeInjectModule.java
@@ -0,0 +1,97 @@
+/*
+ * Jooby https://jooby.io
+ * Apache License Version 2.0 https://jooby.io/LICENSE.txt
+ * Copyright 2014 Edgar Espina
+ */
+package io.jooby.avaje.inject;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.typesafe.config.Config;
+
+import io.avaje.inject.BeanScope;
+import io.avaje.inject.BeanScopeBuilder;
+import io.jooby.Extension;
+import io.jooby.Jooby;
+
+/**
+ * Avaje Inject module: https://jooby.io/modules/avaje-inject.
+ *
+ * Jooby integrates the {@link io.jooby.ServiceRegistry} into the Avaje DI framework.
+ *
+ *
Usage:
+ *
+ *
{@code
+ * {
+ *
+ *
+ * install(AvajeInjectModule.of());
+ *
+ * }
+ *
+ * }
+ *
+ * Require calls are going to be resolved by Avaje inject now.
+ *
+ * @author josiah
+ * @since 3.0.0
+ */
+public class AvajeInjectModule implements Extension {
+
+ private final BeanScopeBuilder beanScope;
+
+ public static AvajeInjectModule of() {
+ return new AvajeInjectModule(BeanScope.builder());
+ }
+
+ public static AvajeInjectModule of(BeanScopeBuilder beanScope) {
+ return new AvajeInjectModule(beanScope);
+ }
+
+ AvajeInjectModule(BeanScopeBuilder beanScope) {
+ this.beanScope = beanScope;
+ }
+
+ @Override
+ public boolean lateinit() {
+ return true;
+ }
+
+ @Override
+ public void install(Jooby application) throws Exception {
+
+ application
+ .getServices()
+ .entrySet()
+ .forEach(
+ e -> {
+ final var key = e.getKey();
+ if (key.getName() == null) {
+ beanScope.provideDefault(key.getType(), e::getValue);
+ } else {
+ beanScope.bean(key.getName(), key.getType(), e.getValue());
+ }
+ });
+
+ final var environment = application.getEnvironment();
+ beanScope.profiles(environment.getActiveNames().toArray(String[]::new));
+
+ // configuration properties
+ final var config = environment.getConfig();
+ beanScope.propertyPlugin(new JoobyPropertyPlugin(config));
+ beanScope.bean(Config.class, config);
+
+ for (var entry : config.entrySet()) {
+ String name = entry.getKey();
+ Object value = entry.getValue().unwrapped();
+
+ if (value instanceof List> values) {
+ value = values.stream().map(Object::toString).collect(Collectors.joining(","));
+ }
+ beanScope.bean(name, String.class, value.toString());
+ }
+
+ application.registry(new AvajeInjectRegistry(beanScope.build()));
+ }
+}
diff --git a/modules/jooby-avaje-inject/src/main/java/io/jooby/avaje/inject/AvajeInjectRegistry.java b/modules/jooby-avaje-inject/src/main/java/io/jooby/avaje/inject/AvajeInjectRegistry.java
new file mode 100644
index 0000000000..6123bbba70
--- /dev/null
+++ b/modules/jooby-avaje-inject/src/main/java/io/jooby/avaje/inject/AvajeInjectRegistry.java
@@ -0,0 +1,42 @@
+package io.jooby.avaje.inject;
+
+import java.util.NoSuchElementException;
+
+import io.avaje.inject.BeanScope;
+import io.jooby.Registry;
+import io.jooby.ServiceKey;
+import io.jooby.exception.RegistryException;
+
+class AvajeInjectRegistry implements Registry {
+
+ private final BeanScope beanScope;
+
+ public AvajeInjectRegistry(BeanScope beanScope) {
+ this.beanScope = beanScope;
+ }
+
+ @Override
+ public T require(Class type) throws RegistryException {
+ try {
+ return beanScope.get(type);
+ } catch (NoSuchElementException e) {
+ ServiceKey key = ServiceKey.key(type);
+ throw new RegistryException("Provisioning of `" + key + "` resulted in exception", e);
+ }
+ }
+
+ @Override
+ public T require(Class type, String name) throws RegistryException {
+ try {
+ return beanScope.get(type, name);
+ } catch (NoSuchElementException e) {
+ ServiceKey key = ServiceKey.key(type, name);
+ throw new RegistryException("Provisioning of `" + key + "` resulted in exception", e);
+ }
+ }
+
+ @Override
+ public T require(ServiceKey key) throws RegistryException {
+ return require(key.getType(), key.getName());
+ }
+}
diff --git a/modules/jooby-avaje-inject/src/main/java/io/jooby/avaje/inject/JoobyPropertyPlugin.java b/modules/jooby-avaje-inject/src/main/java/io/jooby/avaje/inject/JoobyPropertyPlugin.java
new file mode 100644
index 0000000000..246ed35665
--- /dev/null
+++ b/modules/jooby-avaje-inject/src/main/java/io/jooby/avaje/inject/JoobyPropertyPlugin.java
@@ -0,0 +1,32 @@
+package io.jooby.avaje.inject;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import com.typesafe.config.Config;
+
+import io.avaje.inject.spi.PropertyRequiresPlugin;
+
+public class JoobyPropertyPlugin implements PropertyRequiresPlugin {
+
+ private final Config config;
+
+ public JoobyPropertyPlugin(Config config) {
+ this.config = config;
+ }
+
+ @Override
+ public Optional get(String property) {
+ return Optional.ofNullable(config.getString(property));
+ }
+
+ @Override
+ public boolean contains(String property) {
+ return config.hasPath(property);
+ }
+
+ @Override
+ public boolean equalTo(String property, String value) {
+ return config.hasPath(property) && Objects.equals(config.getString(property), value);
+ }
+}
diff --git a/modules/jooby-avaje-inject/src/main/java/module-info.java b/modules/jooby-avaje-inject/src/main/java/module-info.java
new file mode 100644
index 0000000000..341614c740
--- /dev/null
+++ b/modules/jooby-avaje-inject/src/main/java/module-info.java
@@ -0,0 +1,13 @@
+/*
+ * Jooby https://jooby.io
+ * Apache License Version 2.0 https://jooby.io/LICENSE.txt
+ * Copyright 2014 Edgar Espina
+ */
+/** Avaje Inject module. */
+module io.jooby.avaje.inject {
+ exports io.jooby.avaje.inject;
+
+ requires transitive io.jooby;
+ requires transitive typesafe.config;
+ requires transitive io.avaje.inject;
+}
diff --git a/modules/jooby-avaje-jsonb/pom.xml b/modules/jooby-avaje-jsonb/pom.xml
index 6a81da793d..78a168ccfd 100644
--- a/modules/jooby-avaje-jsonb/pom.xml
+++ b/modules/jooby-avaje-jsonb/pom.xml
@@ -24,6 +24,12 @@
avaje-jsonb
+
+ io.avaje
+ avaje-jsonb-generator
+ provided
+
+
io.jooby
diff --git a/modules/jooby-bom/pom.xml b/modules/jooby-bom/pom.xml
index 88f73d14ff..97c5517d53 100644
--- a/modules/jooby-bom/pom.xml
+++ b/modules/jooby-bom/pom.xml
@@ -29,6 +29,11 @@
jooby
${project.version}
+
+ io.jooby
+ jooby-avaje-inject
+ ${project.version}
+
io.jooby
jooby-avaje-jsonb
diff --git a/modules/pom.xml b/modules/pom.xml
index b1144713ea..9438c2db27 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -64,6 +64,7 @@
jooby-quartz
jooby-awssdk-v1
+ jooby-avaje-inject
jooby-guice
jooby-commons-email
diff --git a/pom.xml b/pom.xml
index 1c4d768073..4d543bc7d0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,6 +47,7 @@
1.4.3
+ 9.12
7.0.0
@@ -673,6 +674,19 @@
jackson-datatype-hibernate5
${jackson.version}
+
+
+
+ io.avaje
+ avaje-inject
+ ${avaje-inject.version}
+
+
+
+ io.avaje
+ avaje-inject-generator
+ ${avaje-inject.version}
+
@@ -681,6 +695,12 @@
${avaje-jsonb.version}
+
+ io.avaje
+ avaje-jsonb-generator
+ ${avaje-jsonb.version}
+
+
org.freemarker