title: Restart/Reload Spring Data MongoDB
body: <p>Within my project, I am using a property placeholder to read a property file, containing the configuration for my database connection. During my initial setup and reconfiguration at some point later I want to be able to change the details of the database host. </p>
  
  <p>I tried to use the refresh() method called on the current application context, but somehow the Spring Data Beans are not reloaded and I am getting an IllegalStateException issued by Spring Data:</p>
  
  <pre><code>HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException: open
  Exception report: Message: Request processing failed; nested exception is java.lang.IllegalStateException: open description: The server encountered an internal error that prevented it from fulfilling this request. exception: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: open
      org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
      org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
      javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
      org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
      javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
      org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
      org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:139)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
      org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
      org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
      org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
      org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
  root cause: java.lang.IllegalStateException: open
      org.bson.util.Assertions.isTrue(Assertions.java:36)
      com.mongodb.DBTCPConnector.getPrimaryPort(DBTCPConnector.java:408)
      com.mongodb.DBCollectionImpl.update(DBCollectionImpl.java:263)
      com.mongodb.DBCollection.update(DBCollection.java:191)
      com.mongodb.DBCollection.save(DBCollection.java:975)
      com.mongodb.DBCollection.save(DBCollection.java:934)
      org.springframework.data.mongodb.core.MongoTemplate$10.doInCollection(MongoTemplate.java:950)
      org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:410)
      org.springframework.data.mongodb.core.MongoTemplate.saveDBObject(MongoTemplate.java:945)
      org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:885)
      org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:833)
      org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:73)
      sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      java.lang.reflect.Method.invoke(Method.java:483)
      org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:442)
      org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:427)
      org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:381)
      org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      org.springframework.data.repository.core.support.RepositoryFactorySupport$DefaultMethodInvokingMethodInterceptor.invoke(RepositoryFactorySupport.java:512)
      org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
      com.sun.proxy.$Proxy2987.save(Unknown Source)
      de.steilerdev.myVerein.server.controller.InitController.initSuperAdmin(InitController.java:158)
      sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      java.lang.reflect.Method.invoke(Method.java:483)
      org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
      org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
      org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
      org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
      org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
      org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
      org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
      org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
      org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
      org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
      javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
      org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
      javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
      org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
      org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:139)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
      org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
      org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
      org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
      org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
  </code></pre>
  
  <p>Unfortunately I am not very confident with beans and their lifecycle, so I need help reloading the appropriate bean. I would also be okay with the possibility to restart the Spring application itself, even though it would be an expensive operation. Since it is only needed very rarely I would be okay with the costs of that.</p>
  
  <p>I am not sure which parts of the code you need, but here is a link to the Github repository. (Sorry for the poor documentation, still at the beginning of the project)</p>
  
  <p>Thanks!</p>
  
  <hr>
  
  <p>Edit: Some classes involved in the process:</p>
  
  <p><a href="https://github.com/steilerDev/myVerein/blob/master/Code/Server/src/main/java/de/steilerdev/myVerein/server/controller/InitController.java" rel="nofollow">de.steilerdev.myVerein.server.controller.InitController</a> (Receiving the related request, storing the settings to my SettingsRepository)</p>
  
  <pre><code>@Controller
  @RequestMapping("/init")
  public class InitController
  {
      @Autowired
      private SettingsRepository settingsRepository;
  
      @Autowired
      private UserRepository userRepository;
  
      @Autowired
      private DivisionRepository divisionRepository;
  
      @Autowired
      private ReloadableResourceBundleMessageSource messageSource;
  
      private static Logger logger = LoggerFactory.getLogger(InitController.class);
  
      @RequestMapping(value = "settings")
      public ResponseEntity&lt;String&gt; initSettings(@RequestParam String clubName,
                                                 @RequestParam String databaseHost,
                                                 @RequestParam String databasePort,
                                                 @RequestParam String databaseUser,
                                                 @RequestParam String databasePassword,
                                                 @RequestParam String databaseCollection,
                                                 @RequestParam String rememberMeTokenKey,
                                                 Locale locale)
      {
          logger.debug("Starting initial configuration");
          if(!settingsRepository.isInitSetup())
          {
              logger.warn("An initial setup API was used, even though the system is already configured.");
              return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.settings.notAllowed", null, "You are not allowed to perform this action at the moment", locale), HttpStatus.BAD_REQUEST);
          } else if(clubName.isEmpty() || rememberMeTokenKey.isEmpty())
          {
              logger.warn("The club name or remember me key is not present");
              return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.settings.noKeyOrName", null, "The club name and remember me key is required", locale), HttpStatus.BAD_REQUEST);
          } else
          {
              int databasePortInt = 27017;
              if(databaseHost.isEmpty())
              {
                  logger.warn("The database host is empty, using default value.");
                  databaseHost = "localhost";
              }
              if(databasePort.isEmpty())
              {
                  logger.warn("The database port is empty, using default value.");
                  databasePort = "27017";
              } else
              {
                  try
                  {
                      databasePortInt = Integer.parseInt(databasePort);
                  } catch (NumberFormatException e)
                  {
                      logger.warn("The database port seems not to be a number " + databasePort);
                      return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.settings.dbPortNoNumber", null, "The database port needs to be a number", locale), HttpStatus.BAD_REQUEST);
                  }
              }
              if(databaseCollection.isEmpty())
              {
                  logger.warn("The database collection name is empty, using default value");
                  databaseCollection = "myVerein";
              }
  
              if(!mongoIsAvailable(databaseHost, databasePortInt, databaseUser, databasePassword, databaseCollection))
              {
                  logger.warn("The stated MongoDB is not available");
                  return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.settings.mongoNotAvailable", null, "The stated MongoDB is not available", locale), HttpStatus.BAD_REQUEST);
              }
  
              try
              {
                  logger.debug("Temporarily storing information");
                  settingsRepository.setClubName(clubName);
                  settingsRepository.setDatabaseHost(databaseHost);
                  settingsRepository.setDatabasePort(databasePort);
                  settingsRepository.setDatabaseUser(databaseUser);
                  settingsRepository.setDatabasePassword(databasePassword);
                  settingsRepository.setDatabaseName(databaseCollection);
                  settingsRepository.setRememberMeKey(rememberMeTokenKey);
              } catch (IOException e)
              {
                  logger.warn("Unable to save settings.");
                  return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.settings.savingSettingsError", null, "Unable to save settings, please try again", locale), HttpStatus.INTERNAL_SERVER_ERROR);
              }
              return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.settings.savingSettingsSuccess", null, "Successfully saved settings", locale), HttpStatus.OK);
          }
      }
  
      @RequestMapping(value = "superAdmin")
      public ResponseEntity&lt;String&gt; initSuperAdmin(@RequestParam String firstName,
                                                   @RequestParam String lastName,
                                                   @RequestParam String email,
                                                   @RequestParam String password,
                                                   @RequestParam String passwordRe,
                                                   Locale locale)
      {
          if(!settingsRepository.isInitSetup())
          {
              logger.warn("An initial setup API was used, even though the system is already configured.");
              return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.admin.notAllowed", null, "You are not allowed to perform this action at the moment", locale), HttpStatus.BAD_REQUEST);
          } else if(firstName.isEmpty() || lastName.isEmpty() || email.isEmpty() || password.isEmpty() || passwordRe.isEmpty())
          {
              logger.warn("A required parameter of the super admin is empty or missing during initial configuration");
              return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.admin.missingParameter", null, "A required parameter is empty or missing", locale), HttpStatus.BAD_REQUEST);
          } else if(!password.equals(passwordRe))
          {
              logger.warn("The password and the re-typed password do not match!");
              return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.admin.passwordMatchError", null, "The password and the re-typed password do not match", locale), HttpStatus.BAD_REQUEST);
          } else
          {
              logger.debug("Creating a new initial user.");
              User superAdmin = new User();
              superAdmin.setFirstName(firstName);
              superAdmin.setLastName(lastName);
              superAdmin.setEmail(email);
              superAdmin.setPassword(password);
  
              logger.debug("Creating a new initial root division.");
              Division rootDivision = new Division(settingsRepository.getClubName(), null, superAdmin, null);
  
              //Saving changes and restarting context
              try
              {
                  settingsRepository.setInitSetup(false);
                  //This call is restarting the application.
                  settingsRepository.saveSettings(superAdmin);
              } catch (IOException e)
              {
                  logger.warn("Unable to save settings.");
                  return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.admin.savingSettingsError", null, "Unable to save settings, please try again", locale), HttpStatus.INTERNAL_SERVER_ERROR);
              }
  
              try
              {
                  userRepository.save(superAdmin);
                  divisionRepository.save(rootDivision);
              } catch (ConstraintViolationException e)
              {
                  logger.warn("A database constraint was violated while saving the new super admin.");
                  return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.admin.constraintViolation", null, "A database constraint was violated while saving the new super admin", locale), HttpStatus.BAD_REQUEST);
              }
              return new ResponseEntity&lt;&gt;(messageSource.getMessage("init.message.admin.savingAdminSuccess", null, "Successfully saved the new super admin. The settings are now being saved and the application is restarted.", locale) , HttpStatus.OK);
          }
      }
  
      private boolean mongoIsAvailable(String databaseHost, int databasePort, String databaseUser, String databasePassword, String databaseCollection)
      {
          logger.debug("Creating mongo client to test connection");
          List&lt;MongoCredential&gt; credential = null;
          MongoClient mongoClient = null;
          if(!databaseUser.isEmpty() &amp;&amp; !databasePassword.isEmpty())
          {
              credential = Arrays.asList(MongoCredential.createMongoCRCredential(databaseUser, databaseCollection, databasePassword.toCharArray()));
          }
  
          try
          {
              mongoClient = new MongoClient(new ServerAddress(databaseHost, databasePort),credential);
  
              //Checking if connection REALLY works
              List&lt;String&gt; databases = mongoClient.getDatabaseNames();
              if(databases == null)
              {
                  logger.warn("The list of databases is null");
                  return false;
              } else if(databases.isEmpty())
              {
                  logger.info("The databases are empty");
                  return true;
              } else
              {
                  logger.debug("The database connection seems okay.");
                  return true;
              }
          } catch (UnknownHostException e)
          {
              logger.warn("Unable to resolve mongoDB host: " + e.getMessage());
              return false;
          } catch (MongoException e)
          {
              logger.warn("Unable to receive list of present databases: " + e.getMessage());
              return false;
          } finally
          {
              if(mongoClient != null)
              {
                  mongoClient.close();
              }
          }
      }
  }
  </code></pre>
  
  <p><a href="https://github.com/steilerDev/myVerein/blob/master/Code/Server/src/main/java/de/steilerdev/myVerein/server/model/SettingsRepository.java" rel="nofollow">de.steilerdev.myVerein.server.model.SettingsRepository</a> (Retrieving and storing the settings persistent within a properties file, as well as restarting the application if the settings changed)</p>
  
  <pre><code>public class SettingsRepository
  {
      @Autowired
      private MongoTemplate mongoTemplate;
  
      @Autowired
      private SimpleMongoDbFactory mongoDbFactory;
  
      @Autowired
      private ApplicationContext applicationContext;
  
      private Properties settings;
      private Resource settingsResource;
  
      private final static String settingsFileName = "myVerein.properties";
      //Property names
      private final static String databaseName = "dbName";
      private final static String databaseHost = "dbHost";
      private final static String databasePort = "dbPort";
      private final static String databaseUser = "dbUser";
      private final static String databasePassword = "dbPassword";
      private final static String rememberMeKey = "rememberMeKey";
      private final static String clubName = "clubName";
      private final static String initSetup = "initSetup";
  
      private boolean changed;
      private boolean databaseChanged;
  
      private static Logger logger = LoggerFactory.getLogger(SettingsRepository.class);
  
      public Properties loadSettings() throws IOException
      {
          if(settings == null)
          {
              logger.debug("Loading settings file from classpath");
              settingsResource = new ClassPathResource(settingsFileName);
              changed = false;
              databaseChanged = false;
              return (settings = PropertiesLoaderUtils.loadProperties(settingsResource));
          } else
          {
              return settings;
          }
      }
  
      //Getter and setter removed
  
      public void saveSettings(User currentUser) throws IOException
      {
          saveSettings(loadSettings(), currentUser);
      }
  
      public void saveSettings(Properties settings, User currentUser) throws IOException
      {
          if(changed)
          {
              logger.debug("Saving settings to " + settingsResource.getFile().getAbsolutePath());
              settings.store(new FileOutputStream(settingsResource.getFile()), "Settings last changed " + (currentUser != null ? ("by " + currentUser.getEmail() + " (" + LocalDateTime.now().toString() + ")") : LocalDateTime.now().toString()));
              if(databaseChanged)
              {
                  try
                  {
                      mongoDbFactory.destroy();
                  } catch (Exception e)
                  {
                      System.err.println("Problem destroying factory");
                  }
                  ((ConfigurableApplicationContext) applicationContext).refresh();
              }
              this.settings = null;
          } else
          {
              logger.debug("No need to save the settings");
          }
      }
  }
  </code></pre>
  
  <p>The exception is thrown in line 178 of the InitController, which means after reloading and during saving an object to the new controller <code>userRepository.save(superAdmin);</code></p>