Skip to content

How to retrieve@Named value in Micronaut 3 #5743

Open
@sdelamo

Description

@sdelamo

Micronaut 2.5.8

package com.example;
public interface FooApi {
}
package com.example;

import javax.inject.Named;
import javax.inject.Singleton;

@Named("generator")
@Singleton
public class DefaultFooApi implements FooApi {
}

Following test is green:

package com.example;

import io.micronaut.context.ApplicationContext;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import java.lang.annotation.Annotation;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

@MicronautTest(startApplication = false)
public class FooApiNamedGeneratorTest {

    @Inject
    ApplicationContext applicationContext;

    @Testpublic void fooApiIsAnnoatedWithNamedGeneratorViaAnnotationMetadata() {
        assertTrue(fetchBeanName(FooApi.class, "javax.inject.Named").isPresent());
        assertEquals("generator", fetchBeanName(FooApi.class,  "javax.inject.Named").get());
    }

    @Testpublic void fooApiIsAnnoatedWithNamedGeneratorViaAnnotationNameByStereoType() {
        assertTrue(fetchBeanName(FooApi.class, javax.inject.Named.class).isPresent());
        assertEquals("generator", fetchBeanName(FooApi.class,  javax.inject.Named.class).get());
    }

    public Optional<String> fetchBeanName(Class<?> clazz, String annotationName) {
        if (applicationContext.getBeanDefinition(clazz).getAnnotationMetadata().getAnnotation(annotationName) == null) {
            return Optional.empty();
        }
        return applicationContext.getBeanDefinition(clazz).getAnnotationMetadata()
                .getAnnotation(annotationName)
                .getValue(String.class);
    }

    public Optional<String> fetchBeanName(Class<?> clazz, Class<? extends Annotation> namedClass) {
        if (!applicationContext.getBeanDefinition(clazz)
                .getAnnotationNameByStereotype(namedClass)
                .isPresent()) {
            return Optional.empty();
        }
        return applicationContext.getBeanDefinition(clazz)
                .getAnnotationValuesByType(namedClass)
                .stream()
                .filter(annValue -> annValue.getValue(String.class).isPresent())
                .map(annValue -> annValue.getValue(String.class).get())
                .findFirst();
    }
}

Micronaut 3.0.0-SNAPSHOT

I replace:

  • javax.inject.Named with jakarta.inject.Named
  • javax.inject.Singleton with jakarta.inject.Singleton
package com.example;
public interface FooApi {
}
package com.example;

import jakarta.inject.Named;
import jakarta.inject.Singleton;

@Named("generator")
@Singleton
public class DefaultFooApi implements FooApi {
}

In the test I can only retrieve the @Named value if I use javax.inject.Named.

package com.example;

import io.micronaut.context.ApplicationContext;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import jakarta.inject.Inject;
import java.lang.annotation.Annotation;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

@MicronautTest(startApplication = false)
public class FooApiNamedGeneratorTest {

    @Inject
    ApplicationContext applicationContext;


    @Testpublic void fooApiIsAnnoatedWithNamedGeneratorViaAnnotationMetadataWithJakartaName() {
        assertTrue(fetchBeanName(FooApi.class, "jakarta.inject.Named").isPresent());
        assertEquals("generator", fetchBeanName(FooApi.class,  "jakarta.inject.Named").get());
    }
    
    @Testpublic void fooApiIsAnnoatedWithNamedGeneratorViaAnnotationMetadata() {
        assertTrue(fetchBeanName(FooApi.class, "javax.inject.Named").isPresent());
        assertEquals("generator", fetchBeanName(FooApi.class,  "javax.inject.Named").get());
    }

    @Testpublic void fooApiIsAnnoatedWithNamedGeneratorViaAnnotationNameByStereoType() {
        assertTrue(fetchBeanName(FooApi.class, jakarta.inject.Named.class).isPresent());
        assertEquals("generator", fetchBeanName(FooApi.class,  jakarta.inject.Named.class).get());
    }

    public Optional<String> fetchBeanName(Class<?> clazz, String annotationName) {
        if (applicationContext.getBeanDefinition(clazz).getAnnotationMetadata().getAnnotation(annotationName) == null) {
            return Optional.empty();
        }
        return applicationContext.getBeanDefinition(clazz).getAnnotationMetadata()
                .getAnnotation(annotationName)
                .getValue(String.class);
    }

    public Optional<String> fetchBeanName(Class<?> clazz, Class<? extends Annotation> namedClass) {
        if (!applicationContext.getBeanDefinition(clazz)
                .getAnnotationNameByStereotype(namedClass)
                .isPresent()) {
            return Optional.empty();
        }
        return applicationContext.getBeanDefinition(clazz)
                .getAnnotationValuesByType(namedClass)
                .stream()
                .filter(annValue -> annValue.getValue(String.class).isPresent())
                .map(annValue -> annValue.getValue(String.class).get())
                .findFirst();
    }
}

What Is the correct way to see if a bean is annotated with a particular annotation and fetch its value to use BeanDefinition::AnnotationMetadata?

Is not being able to use jakarta.inject.Named a bug?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions