Repository: avaje/avaje-inject
Pull request #763 (2025-01-14 22:04:59)

Fix Avaje HttpClient interface generation error
Fix issue where incorrect predestroy hooks were generated


Patch:
diff --git a/inject-generator/pom.xml b/inject-generator/pom.xml
index 287b7620..e6de7403 100644
--- a/inject-generator/pom.xml
+++ b/inject-generator/pom.xml
@@ -55,6 +55,13 @@
       <version>1.5</version>
       <scope>test</scope>
     </dependency>
+    
+    <dependency>
+      <groupId>io.avaje</groupId>
+      <artifactId>avaje-http-client</artifactId>
+      <version>2.9-RC7</version>
+      <scope>test</scope>
+    </dependency>
 
   </dependencies>
 
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 89aee81e..514f729b 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
@@ -342,7 +342,7 @@ final class BeanReader {
       var priority = preDestroyPriority == null || preDestroyPriority == 1000 ? "" : ", " + preDestroyPriority;
       writer.indent(indent).append(" builder.addPreDestroy($bean::%s%s);", preDestroyMethod.getSimpleName(), priority).eol();
     } else if (typeReader.isClosable() && !prototype) {
-      writer.indent(indent).append(" builder.addPreDestroy($bean);").eol();
+      writer.indent(indent).append(" builder.addAutoClosable($bean);").eol();
     }
   }
 
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/MethodReader.java b/inject-generator/src/main/java/io/avaje/inject/generator/MethodReader.java
index a607732b..4c14b8c1 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/MethodReader.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/MethodReader.java
@@ -293,6 +293,7 @@ final class MethodReader {
             : "builder.addPostConstruct($bean::%s);";
         writer.indent(indent).append(addPostConstruct, initMethod).eol();
       }
+      final var isCloseable = typeReader != null && typeReader.isClosable();
 
       var priority = priority(destroyPriority);
       if (notEmpty(destroyMethod)) {
@@ -302,14 +303,14 @@ final class MethodReader {
             : "builder.addPreDestroy(%s%s);";
         writer.indent(indent).append(addPreDestroy, addPreDestroy(destroyMethod), priority).eol();
 
-      } else if (typeReader != null && typeReader.isClosable()) {
+      } else if (isCloseable && !priority.isBlank()) {
         var addPreDestroy =
           multiRegister
             ? "    .forEach($bean -> builder.addPreDestroy($bean::close%s));"
             : "builder.addPreDestroy($bean::close%s);";
         writer.indent(indent).append(addPreDestroy, priority).eol();
 
-      } else if (beanCloseable) {
+      } else if (isCloseable || beanCloseable) {
         var addAutoClosable =
           multiRegister
             ? "    .forEach(builder::addAutoClosable);"
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/TypeExtendsReader.java b/inject-generator/src/main/java/io/avaje/inject/generator/TypeExtendsReader.java
index 34d55be8..b7e9df67 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/TypeExtendsReader.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/TypeExtendsReader.java
@@ -62,9 +62,12 @@ final class TypeExtendsReader {
    */
   private boolean closeableClient(TypeElement baseType) {
     return ClientPrism.isPresent(baseType)
-      && APContext.typeElement("io.avaje.http.client.HttpClient").getInterfaces().stream()
-      .map(Object::toString)
-      .anyMatch(AutoCloseable.class.getCanonicalName()::equals);
+        && Optional.ofNullable(APContext.typeElement("io.avaje.http.client.HttpClient"))
+            .map(TypeElement::getInterfaces)
+            .stream()
+            .flatMap(List::stream)
+            .map(Object::toString)
+            .anyMatch(AutoCloseable.class.getCanonicalName()::equals);
   }
 
   private boolean autoProvide() {


Test patch:
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lifecycle/ClientFactory.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lifecycle/ClientFactory.java
new file mode 100644
index 00000000..265f60b2
--- /dev/null
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lifecycle/ClientFactory.java
@@ -0,0 +1,13 @@
+package io.avaje.inject.generator.models.valid.lifecycle;
+
+import io.avaje.inject.Bean;
+import io.avaje.inject.Factory;
+
+@Factory
+public class ClientFactory {
+
+  @Bean
+  ClientInterface i() {
+    return null;
+  }
+}
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lifecycle/ClientInterface.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lifecycle/ClientInterface.java
new file mode 100644
index 00000000..38411a68
--- /dev/null
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/lifecycle/ClientInterface.java
@@ -0,0 +1,6 @@
+package io.avaje.inject.generator.models.valid.lifecycle;
+
+import io.avaje.http.api.Client;
+
+@Client
+public interface ClientInterface {}
diff --git a/inject-test/pom.xml b/inject-test/pom.xml
index 50dfa108..23be4bc1 100644
--- a/inject-test/pom.xml
+++ b/inject-test/pom.xml
@@ -81,6 +81,13 @@
       <scope>test</scope>
     </dependency>
 
+    <dependency>
+      <groupId>io.avaje</groupId>
+      <artifactId>avaje-http-client</artifactId>
+      <version>2.9-RC7</version>
+      <scope>test</scope>
+    </dependency>
+
     <dependency>
       <groupId>io.avaje</groupId>
       <artifactId>avaje-jex</artifactId>
diff --git a/inject-test/src/test/java/org/example/coffee/factory/MyFactory.java b/inject-test/src/test/java/org/example/coffee/factory/MyFactory.java
index 1986cf6f..1c388f37 100644
--- a/inject-test/src/test/java/org/example/coffee/factory/MyFactory.java
+++ b/inject-test/src/test/java/org/example/coffee/factory/MyFactory.java
@@ -7,6 +7,7 @@ import org.example.coffee.factory.other.Something;
 
 import jakarta.inject.Named;
 import org.example.coffee.parent.DesEngi;
+import org.example.request.MyHttpClient;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -16,6 +17,19 @@ public class MyFactory {
 
   String methods = "";
 
+  @Bean // (autoCloseable = true)
+  MyHttpClient httpClient() {
+    return new MyHttpClientGenerated();
+  }
+
+  public static class MyHttpClientGenerated implements MyHttpClient, AutoCloseable {
+    public boolean closed;
+    @Override
+    public void close() throws Exception {
+      closed = true;
+    }
+  }
+
   @Bean
   DFact buildDFact() {
     return new DFact();
diff --git a/inject-test/src/test/java/org/example/coffee/factory/MyFactoryTest.java b/inject-test/src/test/java/org/example/coffee/factory/MyFactoryTest.java
index 9a4dcff0..06f1b832 100644
--- a/inject-test/src/test/java/org/example/coffee/factory/MyFactoryTest.java
+++ b/inject-test/src/test/java/org/example/coffee/factory/MyFactoryTest.java
@@ -3,6 +3,7 @@ package org.example.coffee.factory;
 import io.avaje.inject.xtra.ApplicationScope;
 import io.avaje.inject.BeanScope;
 import org.example.coffee.parent.DesEngi;
+import org.example.request.MyHttpClient;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -22,12 +23,15 @@ public class MyFactoryTest {
 
     final MyFactory.MyClose myClose;
     final MyFactory.MyAutoClose myAutoClose;
+    final MyFactory.MyHttpClientGenerated myHttpClientGenerated;
     try (BeanScope context = BeanScope.builder().build()) {
       myClose = context.get(MyFactory.MyClose.class);
       myAutoClose = context.get(MyFactory.MyAutoClose.class);
+      myHttpClientGenerated = (MyFactory.MyHttpClientGenerated) context.get(MyHttpClient.class);
     }
     assertThat(myClose.isClosed()).isTrue();
     assertThat(myAutoClose.isClosed()).isTrue();
+    assertThat(myHttpClientGenerated.closed).isTrue();
   }
 
   @Test
diff --git a/inject-test/src/test/java/org/example/request/MyHttpClient.java b/inject-test/src/test/java/org/example/request/MyHttpClient.java
new file mode 100644
index 00000000..7b99f311
--- /dev/null
+++ b/inject-test/src/test/java/org/example/request/MyHttpClient.java
@@ -0,0 +1,7 @@
+package org.example.request;
+
+import io.avaje.http.api.Client;
+
+@Client
+public interface MyHttpClient {
+}