title: Spring boot adding and removing singleton at runtime
body: <p>With reference with below links, i want my spring boot app to replace bean at runtime in applicationcontext.</p>
  
  <p><a href="https://stackoverflow.com/a/23671942/3349753">Add Bean</a>
  <a href="https://stackoverflow.com/a/6856036/3349753">Remove Bean</a></p>
  
  <p>Below is my try,</p>
  
  <p><strong>MainClass.java</strong></p>
  
  <pre><code>@SpringBootApplication
  public class MainClass {
  
  public static void main(String[] args) {
          SpringApplication.run(
                  MainClass.class, args);
  
          new Thread(new MyThread()).run();
      }
  }
  </code></pre>
  
  <p><strong>ApplicationContextProvider.java</strong></p>
  
  <pre><code>    import org.springframework.beans.BeansException;
      import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
      import org.springframework.beans.factory.support.BeanDefinitionRegistry;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.ApplicationContextAware;
      import org.springframework.context.ConfigurableApplicationContext;
  
      public class ApplicationContextProvider implements ApplicationContextAware {
          private static ApplicationContext context;
  
      public static ApplicationContext getApplicationContext(){
          return context;
      }
  
      @Override
      public void setApplicationContext(ApplicationContext arg0) throws BeansException {
          context = arg0;
  
      }
  
      public Object getBean(String name){
          return context.getBean(name, Object.class);
      }
  
      public void addBean(String beanName, Object beanObject){
          ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext)context).getBeanFactory();
          beanFactory.registerSingleton(beanName, beanObject);
      }
  
      public void removeBean(String beanName){
          BeanDefinitionRegistry reg = (BeanDefinitionRegistry) context.getAutowireCapableBeanFactory();
          reg.removeBeanDefinition(beanName);
      }
  }
  </code></pre>
  
  <p><strong>Config.java</strong></p>
  
  <pre><code>@Configuration
  @ComponentScan(value="com.en.*")
  public class Config {
  
      @Bean
      @Qualifier("myMap")
      public MapBean myMap(){
  
          MapBean bean = new MapBean();
  
          Map&lt;String, String&gt; mp = new HashMap&lt;&gt;();
          mp.put("a", "a");
          bean.setMp(mp);
          return bean;
      }
  
      @Bean
      ApplicationContextProvider applicationContextProvider(){
          return new ApplicationContextProvider();
      }
  
  }
  </code></pre>
  
  <p><strong>MapBean.java</strong></p>
  
  <pre><code>import java.util.Map;
  
  public class MapBean {
  
      private Map&lt;String, String&gt; mp;
  
      public Map&lt;String, String&gt; getMp() {
          return mp;
      }
  
      public void setMp(Map&lt;String, String&gt; mp) {
          this.mp = mp;
      }
  
      @Override
      public String toString() {
          StringBuilder builder = new StringBuilder();
          builder.append("MapBean [mp=");
          builder.append(mp);
          builder.append("]");
          return builder.toString();
      }
  }
  </code></pre>
  
  <p><strong>MyThread.java</strong></p>
  
  <pre><code>import java.util.HashMap;
  import java.util.Map;
  
  import com.en.model.MapBean;
  
  public class MyThread implements Runnable{
  
      static ApplicationContextProvider appCtxPrvdr = new ApplicationContextProvider();
  
      public void run(){
          try {
              Thread.sleep(5000);
  
              if(ApplicationContextProvider.getApplicationContext().containsBean("myMap")){
                  System.out.println("AppCtx has myMap");
                  MapBean newM = (MapBean) ApplicationContextProvider.getApplicationContext().getBean("myMap", MapBean.class);
                  System.out.println(newM);
                  appCtxPrvdr.removeBean("myMap");
                  System.out.println("Removed myMap from AppCtx");
              }
  
              MapBean bean1 = new MapBean();
              Map&lt;String, String&gt; mp = new HashMap&lt;&gt;();
              mp.put("b", "b");
              bean1.setMp(mp);
  
              appCtxPrvdr.addBean("myMap", bean1);
              System.out.println("myMap added to AppCtx");
  
              if(ApplicationContextProvider.getApplicationContext().containsBean("myMap")){
                  System.out.println("AppCtx has myMap");
                  MapBean newM = (MapBean) ApplicationContextProvider.getApplicationContext().getBean("myMap", MapBean.class);
                  System.out.println(newM);
                  appCtxPrvdr.removeBean("myMap");
                  System.out.println("Removed myMap from AppCtx");
              }
  
              MapBean bean2 = new MapBean();
              Map&lt;String, String&gt; map2 = new HashMap&lt;&gt;();
              map2.put("c", "c");
              bean2.setMp(map2);
  
              appCtxPrvdr.addBean("myMap", bean2);
              System.out.println("myMap added to AppCtx");
              MapBean newM = (MapBean) ApplicationContextProvider.getApplicationContext().getBean("myMap", MapBean.class);
              System.out.println(newM);
  
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  
  }
  </code></pre>
  
  <p>The output i am getting is as below,</p>
  
  <pre><code>AppCtx has myMap
  MapBean [mp={a=a}]
  Removed myMap from AppCtx
  myMap added to AppCtx
  AppCtx has myMap
  MapBean [mp={b=b}]
  org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myMap' available
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.removeBeanDefinition(DefaultListableBeanFactory.java:881)
      at com.en.config.ApplicationContextProvider.removeBean(ApplicationContextProvider.java:47)
      at com.en.config.MyThread.run(MyThread.java:36)
      at java.lang.Thread.run(Unknown Source)
      at com.en.MainClass.main(MainClass.java:77)
  </code></pre>
  
  <p>So as per my understanding below things are happening.</p>
  
  <ol>
  <li>In Config class, it is adding myMap to appctx.</li>
  <li>In Mythread class, it is able to find myMap in appctx.</li>
  <li>It is able to print and then remove from appctx.</li>
  <li>It is able to add new myMap to appctx.</li>
  <li>When above step is done. It is not able to remove it again.</li>
  </ol>
  
  <p>Please advice on how to add and remove it multiple time.</p>