I am working on a project where I generate a class after the spring boot context starts and compile it to the target/classes folder. I know Spring scans the package and registers all the beans in the application context when the application starts. But here, we are generating a class with annotation @Service at runtime, and the application context is unaware of this new bean. So, other beans cannot find this runtime-generated class. This bean is also not in the bean list of Actuator -> Beans in IntelliJ IDEA
When I rerun the application, this runtime-generated bean gets registered in the application context, and other beans can find out or utilize that bean. Actuator -> Beans in IntelliJ IDEA also shows this bean. I want to register this runtime-generated bean to the application context without restarting/rerunning the application. Please let me know what I am missing here.
I tried this, but it did not work for me.
@RestController
@Scope("prototype")
@Slf4j
public class myClass {
@Autowired
private ApplicationContext appContext;
@GetMapping("/beanRegistration")
public void beanRegistration() {
try {
Class<?> generatedClass = Class.forName("myApp.sam.protocompiler.GrpcServerImpl");
log.info("generatedClass : {} | Methods count: {} | Super class : {}", generatedClass.getCanonicalName(), generatedClass.getMethods().length, generatedClass.getSuperclass());
ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) appContext).getBeanFactory();
beanFactory.registerSingleton(generatedClass.getCanonicalName(), generatedClass);
String[] beans = appContext.getBeanDefinitionNames();
Arrays.sort(beans);
for (String bean : beans) {
if(bean.contains(generatedClass.getCanonicalName())) {
System.out.println("New Bean : " + bean);
}
}
} catch (Exception ex) {
log.error("Error : {}", ex.getMessage(), ex);
}
}
}
Also, Is it possible to Scan components after the application is started running? If we can scan runtime-generated components at runtime, we can solve this problem.
Since you are definitely in a Web application, you might try using
GenericWebApplicationContextinstead.Then,
I don't know if this does anything different than what you have, but I think it is the more spring-approved way to do it.