Repository: avaje/avaje-inject
Pull request #737 (2024-11-18 04:45:26)

Fix Lazy Checked Exceptions
Currently, this generates invalid code:
```java
@Singleton
public class LazyBean {
  @Inject Provider<Integer> intProvider;

  public LazyBean() throws Exception {}
}
```

Now properly generates code:

```java
@Generated("io.avaje.inject.generator")
public final class LazyBean$DI  {

  public static void build(Builder builder) {
    if (builder.isAddBeanFor(LazyBean.class)) {
      builder.registerProvider(() -> {
      try {
          var bean = new LazyBean();
          bean.intProvider = builder.getProvider(Integer.class);
          return bean;
      } catch (Throwable e) {
        throw new RuntimeException("Error during wiring", e);
      }
     });
    }
  }

}
```


Patch:
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java b/inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java
index b035859b..458d4239 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java
@@ -337,7 +337,7 @@ final class BeanReader {
   void prototypePostConstruct(Append writer, String indent) {
     if (postConstructMethod != null) {
       var postConstruct = (ExecutableElement) postConstructMethod;
-      writer.append("%s bean.%s(", indent, postConstructMethod.getSimpleName());
+      writer.indent(indent).append(" bean.%s(", postConstructMethod.getSimpleName());
       if (postConstruct.getParameters().isEmpty()) {
         writer.append(");").eol();
       } else {
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/SimpleBeanWriter.java b/inject-generator/src/main/java/io/avaje/inject/generator/SimpleBeanWriter.java
index 9e13867b..17a048b7 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/SimpleBeanWriter.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/SimpleBeanWriter.java
@@ -175,7 +175,15 @@ final class SimpleBeanWriter {
     beanReader.buildAddFor(writer);
     if (beanReader.registerProvider()) {
       indent += "  ";
-      writer.append("      builder.%s(() -> {", beanReader.lazy() ? "registerProvider" : "asPrototype().registerProvider").eol();
+
+      final String registerProvider;
+      if (beanReader.lazy()) {
+        registerProvider = "registerProvider";
+      } else {
+        registerProvider = "asPrototype().registerProvider";
+      }
+
+      writer.append("      builder.%s(() -> {", registerProvider).eol();
     }
     constructor.startTry(writer);
     writeCreateBean(constructor);
@@ -187,11 +195,20 @@ final class SimpleBeanWriter {
     if (beanReader.registerProvider()) {
       beanReader.prototypePostConstruct(writer, indent);
       writer.indent("        return bean;").eol();
-      writer.indent("      });").eol();
+      if (!constructor.methodThrows()) {
+        writer.indent("      });").eol();
+      }
     }
     writeObserveMethods();
     constructor.endTry(writer);
-    writer.append("    }").eol();
+
+    if (beanReader.registerProvider() && constructor.methodThrows()) {
+      writer.append("     }");
+      writer.append(");").eol();
+    }
+
+    writer.append("    }");
+    writer.eol();
   }
 
   private void writeBuildMethodStart() {
@@ -208,13 +225,13 @@ final class SimpleBeanWriter {
 
   private void writeExtraInjection() {
     if (!beanReader.registerProvider()) {
-      writer.indent("      ").append("builder.addInjector(b -> {").eol();
-      writer.indent("      ").append("  // field and method injection").eol();
+      writer.indent(indent).append(" builder.addInjector(b -> {").eol();
+      writer.indent(indent).append("   // field and method injection").eol();
     }
     injectFields();
     injectMethods();
     if (!beanReader.registerProvider()) {
-      writer.indent("      });").eol();
+      writer.indent(indent).append(" });").eol();
     }
   }
 


Test patch:
diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/lazy/LazyBean.java b/blackbox-test-inject/src/main/java/org/example/myapp/lazy/LazyBean.java
index 08555ba6..19a16f91 100644
--- a/blackbox-test-inject/src/main/java/org/example/myapp/lazy/LazyBean.java
+++ b/blackbox-test-inject/src/main/java/org/example/myapp/lazy/LazyBean.java
@@ -17,6 +17,8 @@ public class LazyBean {
 
   @Inject @Nullable AtomicBoolean initialized;
 
+  public LazyBean() throws Exception {}
+
   @PostConstruct
   void init(BeanScope scope) {
     // note that nested test scopes will not be lazy
diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/lazy/LazyFactory.java b/blackbox-test-inject/src/main/java/org/example/myapp/lazy/LazyFactory.java
index 986e46d9..06328273 100644
--- a/blackbox-test-inject/src/main/java/org/example/myapp/lazy/LazyFactory.java
+++ b/blackbox-test-inject/src/main/java/org/example/myapp/lazy/LazyFactory.java
@@ -14,7 +14,7 @@ public class LazyFactory {
 
   @Bean
   @Named("factory")
-  LazyBean lazyInt(@Nullable AtomicBoolean initialized) {
+  LazyBean lazyInt(@Nullable AtomicBoolean initialized) throws Exception {
 
     // note that nested test scopes will not be lazy
     if (initialized != null) initialized.set(true);
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/InjectProcessorTest.java b/inject-generator/src/test/java/io/avaje/inject/generator/InjectProcessorTest.java
index 4e3ca22a..12686f87 100644
--- a/inject-generator/src/test/java/io/avaje/inject/generator/InjectProcessorTest.java
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/InjectProcessorTest.java
@@ -11,6 +11,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Stream;
 
 import javax.tools.JavaCompiler;
@@ -23,16 +24,17 @@ import javax.tools.ToolProvider;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.Disabled;
 
 class InjectProcessorTest {
 
   @AfterEach
   void deleteGeneratedFiles() {
     try {
-      Stream.concat(
+      Stream.of(
               Files.walk(Paths.get("io").toAbsolutePath()),
-              Files.walk(Paths.get("lang").toAbsolutePath()))
+              Files.walk(Paths.get("lang").toAbsolutePath()),
+              Files.walk(Paths.get("util").toAbsolutePath()))
+          .flatMap(Function.identity())
           .sorted(Comparator.reverseOrder())
           .map(Path::toFile)
           .forEach(File::delete);
@@ -41,7 +43,7 @@ class InjectProcessorTest {
     }
   }
 
-  @Disabled
+  //@Disabled
   @Test
   void testGeneration() throws Exception {
     final String source =
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lazy/LazyBean.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lazy/LazyBean.java
index bae70111..2919b2c8 100644
--- a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lazy/LazyBean.java
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lazy/LazyBean.java
@@ -9,4 +9,6 @@ import jakarta.inject.Singleton;
 @Singleton
 public class LazyBean {
   @Inject Provider<Integer> intProvider;
+
+  public LazyBean() throws Exception {}
 }