Search code examples
javainversion-of-controlmicronaut

Prevent NonUniqueBeanException in Micronaut, even with using @Named annotation


Why does this code yield a io.micronaut.context.exceptions.NonUniqueBeanException?

public abstract class ObjectifyRepository<T> {
}

@Singleton
@Named("repositoryA")
public class RepositoryA extends ObjectifyRepository<EntityA> {
    public RepositoryA() {
        super(EntityA.class);
    }
}

@Singleton
@Named("repositoryB")
public class RepositoryB extends ObjectifyRepository<EntityB> {

    public RepositoryB() {
        super(EntityB.class);
    }
}

@Singleton
public class MyService {
    private final RespositoryA repository;

    public MyService(@Named("repositoryA") RespositoryA repository) {
        this.repository = repository;
    }
}

The error message is:

io.micronaut.context.exceptions.NonUniqueBeanException: Multiple possible bean candidates found: [com.example.repository.$RepositoryA$Definition$Intercepted, com.example.repository.$RepositoryB$Definition$Intercepted]

Could this be related to the fact that i extend a base class instead of using interfaces?

Every solution that i found suggested to use the @Named annotations, so i have added them, but it still doesn't resolve my problem.

When i asked ChatGPT it started lying and suggested some imaginary @Type annotation :D


Solution

  • After some trial and error i came up with this working solution:

    public abstract class ObjectifyRepository<T> {
    }
    
    @Singleton
    @Bean(typed = RepositoryA.class)
    public class RepositoryA extends ObjectifyRepository<EntityA> {
        public RepositoryA() {
            super(EntityA.class);
        }
    }
    
    @Singleton
    @Bean(typed = RepositoryB.class)
    public class RepositoryB extends ObjectifyRepository<EntityB> {
    
        public RepositoryB() {
            super(EntityB.class);
        }
    }
    
    @Singleton
    public class MyService {
        private final RespositoryA repository;
    
        public MyService(RespositoryA repository) {
            this.repository = repository;
        }
    }