@PostConstruct is not invoked by Micronaut when a bean with scope @Context is instantiated in @Factory class

744 Views Asked by At

When I create a class annotated with @Context and run a Micronaut application, the @PostConstruct method works.

Example:

package com.example;

import io.micronaut.context.annotation.Context;

import javax.annotation.PostConstruct;

@Context
public class ClassHello1 {

    @PostConstruct
    public void sayHello() {
        System.out.println("Hello from ClassHello1");
    }

    public void doSmth() {
        System.out.println("Doing something...");
    }
}

When I remove @Context annotation from the class ClassHello1 and create a bean with a scope @Context inside @Factory class, @PostConstruct method inside ClassHello1 doesn't work.

Example:

package com.example;

import io.micronaut.context.annotation.Context;
import io.micronaut.context.annotation.Factory;

@Factory
public class FactoryClass {


    @Context
    public ClassHello1 classHello1() {
        return new ClassHello1();
    }
}
-------
package com.example;

import javax.annotation.PostConstruct;

public class ClassHello1 {

    @PostConstruct
    public void sayHello() {
        System.out.println("Hello from ClassHello1");
    }

    public void doSmth() {
        System.out.println("Doing something...");
    }
}

Even if I create another @Context bean and call a method doSmth() of ClassHello1 bean, @PostConstruct in ClassHello1 doesn't work anyway.\

package com.example;

import io.micronaut.context.annotation.Context;
import jakarta.inject.Inject;

import javax.annotation.PostConstruct;

@Context
public class ClassHello2 {

    @Inject
    private ClassHello1 classHello1;

    @PostConstruct
    public void init() {
        classHello1.doSmth();
    }
}

In this example doSmth() method of classHello1 bean is invoked, but annotated with @PostConstruct sayHello() doesn't work.

May you explain to me how can I instantiate ClassHello1 in @Factory class and make its @PostConstruct method work?

Thank you.

1

There are 1 best solutions below

3
ShingJo On BEST ANSWER
public ClassHello1 classHello1() {
        return new ClassHello1(); // <1>
    }
  1. Creating the bean with new will not trigger the @PostConstruct

For example:

import jakarta.annotation.PostConstruct;
import jakarta.inject.Singleton; //preferred over javax

@Singleton // only one instance of the bean will exist (lazy initialization)
// @Prototype // new instance of the bean is created each time it is injected (lazy)
// @Context // created at the same time as the ApplicationContext (eager)
public class Hello {
    @PostConstruct
    public void sayHello() {
        System.out.println("Hello World!");
    }

    public void doSmth() {
        System.out.println("Doing something...");
    }
}

@Controller("/hello")
public class HelloController {

    private final Hello hello;

    public HelloController(Hello hello) {
        this.hello = hello;
    }

    @Get("/injected")
    public String injected() {
        hello.doSmth();
        return "hello.sayHello() was called";
    }

    @Get("/instantiated")
    public String instantiated() {
        Hello h = new Hello();
        h.doSmth();
        return "hello.sayHello() was NOT called";
    }
}