Search code examples
javaspringinversion-of-controlmicronaut

Micronaut - What is Springframework @Bean equivalent?


I am very new to Micronauts and I have a fair bit of experience developing spring boot applications. With this background I was stumbled upon creating custom beans like how I used to create with @Bean annotations on Spring applications. In my case I have a library that provides an Interface and its implementation class. I wanted to use the interface in my code and try to inject the implementation and it failes with below error

Caused by: io.micronaut.context.exceptions.NoSuchBeanException: No bean of type [io.vpv.saml.metadata.service.MetaDataParser] exists for the given qualifier: @Named('MetaDataParserImpl'). Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).

Here is my code

@Singleton
public class ParseMetadataImpl implements ParseMetadata {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Inject
    @Named("MetaDataParserImpl")
    private MetaDataParser metaDataParser;

    @Override
    public IDPMetaData getIDPMetaData(URL url) throws IOException {
        logger.info("Parsing {}", url);
        logger.info("metaDataParser {}", metaDataParser);
        return metaDataParser.parseIDPMetaData(url);
    }
}

I am sure there is somehting wrong I am doing and need to understand what to do. I have this working by adding below code and removing annotations around metaDataParser.

    @PostConstruct
    public void initialize() {
        //Want to Avoid This stuff
        this.metaDataParser = new MetaDataParserImpl();
    }

Using Spring Boot it would be possible to add a @Bean annotation to create some custom beans we can do @Autowired to inject it everywhere on our application. Is there an equivalent on Micronauths that I am missing. I went through the guide on https://docs.micronaut.io/2.0.0.M3/guide/index.html and was not able to get anything to get this working.

Can someone suggest how I can use the @Inject to inject custom beans?

Just incase you want to see this, here is the application on Github. https://github.com/reflexdemon/saml-metadata-viewer


Solution

  • With the help from Deadpool and a bit of reading I got what I was looking for. The solution was creating @BeanFactory

    See Javadoc here: https://docs.micronaut.io/latest/guide/ioc.html#builtInScopes

    The @Prototype annotation is a synonym for @Bean because the default scope is prototype.

    Thus here is an example that will match the the behavior of Spring framework

    Here is the answer for anyone who also is looking for such a thing.

    import io.micronaut.context.annotation.Factory;
    import io.vpv.saml.metadata.service.MetaDataParser;
    import io.vpv.saml.metadata.service.MetaDataParserImpl;
    
    import javax.inject.Singleton;
    // 2024 use: import jakarta.inject.Singleton;
    
    @Factory
    public class BeanFactory {
        @Singleton
        public MetaDataParser getMetaDataParser() {
            return new MetaDataParserImpl();
        }
    }