Bean failiing to initialize in a not deterministic way

Issue

I have a Spring Boot application that has the following bean:

@Configuration
public class ConfigStatus {

    @Value("${olt.id}")
    private int olt_id;

    @Bean
    Status createStatus() {
        return new Status(olt_id);
    }
}

I launch several containers with this application (20 to be exact) and in some of them the bean fails to be initialized and I don’t understand why. The bean is successfuly initialized consistently in 18 of 20 containers. Memory is not an issued as the system I am using has 125gb of ram and at the time of this issue is has 90gb of free memory.

This is the class that makes use of the bean:

@DependsOn("createStatus")
@Service
public class ReceiveMessageHandler {

    Logger log = LoggerFactory.getLogger(this.getClass().getName());
    private static final Gson converter = new Gson();

    @Autowired private Status currentStatus;

    public void handleMessage(String body) {
        OltRequest request = converter.fromJson(body, OltRequest.class);
        request.setStartedBeingProcessedAtOlt(new Date().getTime());
        Response r = new Response(request.getId(), 200, new Date().getTime());
        r.setRequestEnqueuedAtOlt(currentStatus.getEnqueuedAtWorkerTimes().get(request.getId())); // line that fails due to the bean being equal to null
        r.setRequestDequeuedAtOlt(new Date().getTime());
        log.info("Processing request: " + request.getId());
        try {
            Thread.sleep(request.getDuration());
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        request.setEndedBeingProcessedAtOlt(new Date().getTime());
        log.info("Finished processing request: " + request.getId());
        r.setEndedHandling(new Date().getTime());
        Worker.send_response(r, request.getOriginMessage().getWorker());
    }
}

The error messages sais that when the bean was accessed it was null.

In the environment I have another Spring Boot app with 30 running docker containers in which this problem does not occurr, ence my disbelief :D.

Solution

So my assumption (as no stack trace has been provided) is that you should do:

@Configuration
public class ConfigStatus {

    @Bean
    Status currentStatus(@Value("${olt.id}") int olt_id) {
        return new Status(olt_id);
    }
}

I’m not 100% confident if Spring prioritises @Value over @Bean in its instantiation order, so doing this guarantees the ordering. It may be that some of your instances are trying to load the bean before the value is there, so bails out on some NPE.

Also, you should be able to drop the line: @DependsOn("createStatus") in ReceiveMessageHandler.java. Spring runs @Configuration classes before @Service classes, and @Autowired matches on type.

Answered By – Kyri Elia

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published