In the spring boot web application development, you may need to use Application Context to handle loaded beans.The Application context contains all the references to the loaded beans. Spring boot provides a handle for the context of the application. If you use the application context, you may encounter an error message that says “AnnotationConfigApplicationContext has not been refreshed yet.”

In this post, we will see the details of this error message “AnnotationConfigApplicationContext has not yet been refreshed” and how to fix this exception. The error message will be displayed in the console as shown below.

Exception in thread "main" java.lang.IllegalStateException: org.springframework.context.annotation.AnnotationConfigApplicationContext@79c97cb has not been refreshed yet
	at org.springframework.context.support.AbstractApplicationContext.assertBeanFactoryActive(AbstractApplicationContext.java:1092)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1122)
	at com.yawintutor.SpringHelloWorldApplication.main(SpringHelloWorldApplication.java:29)


Root Cause

You tried to use the application context in the spring boot application. The program requests a loaded bean from the application context. As the application context is in-stable, the application context can not provide the requested bean object.

The application context must be converted from a in-stable state to a stable state. The application context has an api called refresh() that converts the application context to the latest beans. Updating the application context will provide a solution for this exception.



How to reproduce this issue

Create an application context from the spring framework in the spring boot application. In the context, add a bean class. Then get the same bean class object from the application context without calling a refresh call. The exception will be thrown from the spring boot application context.

The code below shows how to create this exception. The code contains all the java classes and the pom.xml file.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.8.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.yawintutor</groupId>
	<artifactId>Spring-HelloWorld</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>SpringHelloWorld</name>
	<description>Spring Boot Hello World Project</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Student.java

package com.yawintutor;

public class Student {

	private int id;

	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

MyConfiguration.java

package com.yawintutor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {
	@Bean
	public Student helloWorld() {
		return new Student();
	}
}

SpringHelloWorldApplication.java

package com.yawintutor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.yawintutor.MyConfiguration;
import com.yawintutor.Student;

@SpringBootApplication
public class SpringHelloWorldApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringHelloWorldApplication.class, args);
		
	    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
	    ctx.register(MyConfiguration.class);
	    Student bean = ctx.getBean(Student.class);
	    bean.setId(100);
	    System.out.println(bean.getId());

	}

}


Solution 1

In the example above, after adding the MyConfiguration class, the application context is not refreshed. This class includes a student bean that is not updated in the application context. The code below shows the refresh call context of the application. This is going to solve this exception.

SpringHelloWorldApplication.java

package com.yawintutor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.yawintutor.MyConfiguration;
import com.yawintutor.Student;

@SpringBootApplication
public class SpringHelloWorldApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringHelloWorldApplication.class, args);
		
	    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
	    ctx.register(MyConfiguration.class);
	    
	    ctx.refresh();
	    
	    Student bean = ctx.getBean(Student.class);
	    bean.setId(100);
	    System.out.println(bean.getId());

	}

}


Solution 2

If you call this application context in the controller or component class, you can auto-wire the application context. The following example will show how to apply the context to auto wire

@Controller
public class TestController {

    @Autowired
    private ApplicationContext ctx;
    . . . . . . . . 
    . . . . . . . .

    @RequestMapping(value = "/helloworld", method = RequestMethod.GET)
    public String helloworld() 
    {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        Student student = ctx.getBean(Student.class);
        return "helloworld";
    }
}


Solution 3

The application requires the loaded bean to automatically wire the bean directly instead of loading the application context. The application context is an implicit object. Create an auto wire object for the student class. This will solve the exception.

@Controller
public class TestController {

    @Autowired
    private Student student;
    . . . . . . . . 
    . . . . . . . .

    @RequestMapping(value = "/helloworld", method = RequestMethod.GET)
    public String helloworld() 
    {
        student.setId(100);
        System.out.println("Student id : "+student.getId();
        return "helloworld";
    }
}


Solution 4

The application context handle can be used in the spring boot main method. The code below shows how to get application context handle.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.yawintutor.MyConfiguration;
import com.yawintutor.Student;

@SpringBootApplication
public class SpringHelloWorldApplication {

	public static void main(String[] args) {
	    //SpringApplication.run(SpringHelloWorldApplication.class, args);
		
	    ApplicationContext ctx1 = SpringApplication.run(SpringHelloWorldApplication.class, args);
	    Student bean = ctx1.getBean(Student.class);
	    bean.setId(100);
	    System.out.println(bean.getId());

	}

}



Leave a Reply