Repository: avaje/avaje-inject (java)

Issue:
Named Map beans not working for versions > 9.10
Hello there,

while bumping dependencies (from 9.10-javax to 9.12-javax) my DI setup stopped working. I reproduced the issue in a minimal example:
```java
@Factory
public class ConfigFactory {
    @Bean
    @Named("map1")
    Map<String, Long> map1() {
        return Map.of();
    }

    @Bean
    @Named("map2")
    Map<String, String> map2(Map<String, Long> map1) {
        return Map.of();
    }
}
```
Any advice?

Thanks!

PS: Actually I just realized that dependencies injected via method arguments are not matched by name but by type - is there any way to match them by name? Something like Spring's `@Qualifier`. 

Pull request description:
Fix Factory Map generation
Resolves #582 

Patch:
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/Dependency.java b/inject-generator/src/main/java/io/avaje/inject/generator/Dependency.java
index d5109efb..952afe82 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/Dependency.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/Dependency.java
@@ -24,11 +24,11 @@ final class Dependency {
       this.conditionalDependency = false;
       nameStr = ProcessorUtils.trimAnnotations(name);
     }
-    this.name = nameStr.replace(",", ", ");
+    this.name = nameStr.replace(", ", ",");
   }
 
   Dependency(String name, boolean softDependency) {
-    this.name = ProcessorUtils.trimAnnotations(name).replace(",", ", ");
+    this.name = ProcessorUtils.trimAnnotations(name).replace(", ", ",");
     this.softDependency = softDependency;
     this.conditionalDependency = false;
   }
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/FieldReader.java b/inject-generator/src/main/java/io/avaje/inject/generator/FieldReader.java
index d9f57037..591c58fd 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/FieldReader.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/FieldReader.java
@@ -21,8 +21,8 @@ final class FieldReader {
     this.element = element;
     this.name = Util.getNamed(element);
     this.nullable = Util.isNullable(element);
-    this.utype = Util.determineType(element.asType());
     this.isBeanMap = QualifiedMapPrism.isPresent(element);
+    this.utype = Util.determineType(element.asType(), isBeanMap);
     this.fieldType = Util.unwrapProvider(utype.rawType(isBeanMap));
     this.type = utype.toUType();
     this.assisted = AssistedPrism.isPresent(element);
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/MetaDataOrdering.java b/inject-generator/src/main/java/io/avaje/inject/generator/MetaDataOrdering.java
index f4ed0020..0c4d175b 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/MetaDataOrdering.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/MetaDataOrdering.java
@@ -59,7 +59,7 @@ final class MetaDataOrdering {
   }
 
   private ProviderList providerAdd(String requireType) {
-    return providers.computeIfAbsent(requireType, s -> new ProviderList());
+    return providers.computeIfAbsent(requireType.replace(", ", ","), s -> new ProviderList());
   }
 
   int processQueue() {
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 8f10416b..832d0d71 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
@@ -486,8 +486,8 @@ final class MethodReader {
       this.simpleName = param.getSimpleName().toString();
       this.named = Util.getNamed(param);
       this.nullable = Util.isNullable(param);
-      this.utilType = Util.determineType(param.asType());
       this.isBeanMap = QualifiedMapPrism.isPresent(param);
+      this.utilType = Util.determineType(param.asType(), isBeanMap);
       this.paramType = utilType.rawType(isBeanMap);
       this.genericType = utilType.toUType();
       this.fullUType = UType.parse(param.asType());
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/Util.java b/inject-generator/src/main/java/io/avaje/inject/generator/Util.java
index 1ab8810d..00a9f6a8 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/Util.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/Util.java
@@ -208,8 +208,8 @@ final class Util {
     return valType;
   }
 
-  static UtilType determineType(TypeMirror rawType) {
-    return UtilType.of(rawType.toString(), rawType);
+  static UtilType determineType(TypeMirror rawType, boolean beanMap) {
+    return UtilType.of(rawType.toString(), beanMap, rawType);
   }
 
   /**
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/UtilType.java b/inject-generator/src/main/java/io/avaje/inject/generator/UtilType.java
index 34ccc668..824d4d17 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/UtilType.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/UtilType.java
@@ -23,14 +23,14 @@ final class UtilType {
     this.uType = uType;
   }
 
-  static UtilType of(String rawType, TypeMirror mirror) {
+  static UtilType of(String rawType, boolean beanMap, TypeMirror mirror) {
     var uType = UType.parse(mirror);
     if (rawType.startsWith("java.util.List<")) {
       return new UtilType(Type.LIST, rawType, uType.param0());
     } else if (rawType.startsWith("java.util.Set<")) {
       return new UtilType(Type.SET, rawType, uType.param0());
     } else if (rawType.startsWith("java.util.Map<java.lang.String,")) {
-      return new UtilType(Type.MAP, rawType, uType.param1());
+      return new UtilType(Type.MAP, rawType, beanMap ? uType.param1() : uType);
     } else if (rawType.startsWith("java.util.Optional<")) {
       return new UtilType(Type.OPTIONAL, rawType, uType.param0());
     } else if (Util.isProvider(rawType)) {


Test patch:
diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/other/ConfigFactory.java b/blackbox-test-inject/src/main/java/org/example/myapp/other/ConfigFactory.java
new file mode 100644
index 00000000..a54fca82
--- /dev/null
+++ b/blackbox-test-inject/src/main/java/org/example/myapp/other/ConfigFactory.java
@@ -0,0 +1,23 @@
+package org.example.myapp.other;
+
+import io.avaje.inject.Bean;
+import io.avaje.inject.Factory;
+import jakarta.inject.Named;
+
+import java.util.Map;
+
+@Factory
+class ConfigFactory {
+
+  @Bean
+  @Named("map1")
+  Map<String, Long> map1() {
+    return Map.of("one", 1L, "two", 2L);
+  }
+
+  @Bean
+  @Named("map2")
+  Map<String, String> map2(Map<String, Long> map1) {
+    return Map.of("a","hi", "b", "there", "count", String.valueOf(map1.size()));
+  }
+}
diff --git a/blackbox-test-inject/src/test/java/org/example/myapp/other/ConfigFactoryTest.java b/blackbox-test-inject/src/test/java/org/example/myapp/other/ConfigFactoryTest.java
new file mode 100644
index 00000000..49af8600
--- /dev/null
+++ b/blackbox-test-inject/src/test/java/org/example/myapp/other/ConfigFactoryTest.java
@@ -0,0 +1,30 @@
+package org.example.myapp.other;
+
+import io.avaje.inject.BeanScope;
+import io.avaje.inject.spi.GenericType;
+import org.example.myapp.generic.Generic;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ConfigFactoryTest {
+
+  final Type TYPE_MapStringString = new GenericType<Map<String, String>>(){}.type();
+  final Type TYPE_MapStringLong = new GenericType<Map<String, Long>>(){}.type();
+
+  @SuppressWarnings("unchecked")
+  @Test
+  void doStuff() {
+    try (BeanScope beanScope = BeanScope.builder().build()) {
+
+      var map1 = (Map<String,String>)beanScope.get(TYPE_MapStringString);
+      var map2 = (Map<String,Long>)beanScope.get(TYPE_MapStringLong);
+
+      assertThat(map1).containsKeys("a", "b", "count");
+      assertThat(map2).containsKeys("one", "two");
+    }
+  }
+}
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/ConfigFactory.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/ConfigFactory.java
new file mode 100644
index 00000000..ebe92f63
--- /dev/null
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/ConfigFactory.java
@@ -0,0 +1,22 @@
+package io.avaje.inject.generator.models.valid;
+
+import java.util.Map;
+
+import io.avaje.inject.Bean;
+import io.avaje.inject.Factory;
+import jakarta.inject.Named;
+
+@Factory
+public class ConfigFactory {
+  @Bean
+  @Named("map1")
+  Map<String, Long> map1() {
+    return Map.of();
+  }
+
+  @Bean
+  @Named("map2")
+  Map<String, String> map2(@Named("map1") Map<String, Long> map1) {
+    return Map.of();
+  }
+}