Есть ли способ проверить правильность подключения mongoDB?

В моем приложении весенней загрузки я использую spring-boot-starter-data-mongodb:2.1.3, чтобы получить соединение для MongoDB. У меня есть файл свойств для настройки mongoDB:

 spring.data.mongodb.host=localhost
 spring.data.mongodb.port=27017
 spring.data.mongodb.database=database

Если я укажу неправильное имя хоста (spring.data.mongodb.host=incorrect host) или порт, мое приложение запустится успешно. Но я хочу, чтобы это приложение потерпело неудачу так же, как если бы я установил имя хоста в неправильном формате (spring.data.mongodb.host=hxxt://wrongFormat)

Caused by: com.mongodb.MongoException: host and port should be specified in host:port format

Как я могу это сделать?

Пример:

приложение.propertires

 #Wrong host
 spring.data.mongodb.host=www.google.com
 spring.data.mongodb.port=27017
 spring.data.mongodb.database=database

Демонстрационное приложение.java:

 @SpringBootApplication
 public class DemoApplication {
    public static void main(String[] args) {
       SpringApplication.run(DemoApplication.class, args);
    }
 }

Конфиг.java:

@Configuration
public class Config {
    @Bean
    public CommandLineRunner commandLineRunner(JobRepository jobRepository ){
        return args -> jobRepository.findById("1");
    }
}  

JobRepository.java:

  public interface JobRepository extends MongoRepository<Job, String> {}

Работа.java:

  @Getter
  @Setter
  @EqualsAndHashCode
  @NoArgsConstructor
  @Document(collection = "Jobs")
  public class Job {
     @Id
     private String id = null;
     private String field;
  }

person Stanislav Serdiuk    schedule 17.05.2019    source источник
comment
вы можете загрузить свойства в класс-оболочку и проверить одно за другим для этих основных, если формат параметров правильный. Если нет, запишите ошибку и выдайте исключение/System.exit(0)   -  person aran    schedule 17.05.2019
comment
какая версия весенней загрузки и весенних данных mongodb? Я пробовал, не запустилось, и быстро потерпел неудачу с spring boot 2.1.3.RELEASE   -  person Barath    schedule 17.05.2019
comment
@Barath, я использую spring-boot-starter-data-mongodb версии 2.1.3. Какое имя хоста или порт вы установили? Если я попытаюсь использовать имя хоста www.google.com, мое приложение запустится успешно. Ошибка возникает при неправильном формате. Я хочу получить сообщение об ошибке, когда база данных недоступна, и прервать запуск приложения.   -  person Stanislav Serdiuk    schedule 18.05.2019
comment
Это прерывается, пожалуйста, смотрите журналы здесь com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {type=UNKNOWN, servers=[{address=www.google.com:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.SocketTim   -  person Barath    schedule 18.05.2019
comment
Пожалуйста, поделитесь примером проекта, чтобы воспроизвести проблему.   -  person Barath    schedule 18.05.2019
comment
@Barath, я добавил пример, см. основную тему. Я получаю такое же исключение только после запуска моего приложения и попытки использовать репозиторий mongo. Но запуск не прерывается и приложение продолжает работать.   -  person Stanislav Serdiuk    schedule 20.05.2019
comment
@StanislavSerdiuk, пожалуйста, проверьте ответ и образец для тестирования   -  person Barath    schedule 20.05.2019


Ответы (2)


Ваша проблема в том, что проверка соединения на монго происходит асинхронно. Итак, если ввод правильный, все bean-компоненты создаются весенней загрузкой, и соединение завершается сбоем на более позднем этапе. Вы можете заставить его взорваться, определив bean-компонент, который проверяет соединение при запуске. Например, я использую это:

/**
 * This is a testing bean. It is only here to explode when the database is not available.
 * This is to counter act default spring boot behaviour where the Mongo configuration
 * will connect to a localhost DB regardless of whether it exists or not.  
 *
 */
public class MongoDatabaseVerifier {
    private static final Logger log = LoggerFactory.getLogger(MongoDatabaseVerifier.class);

    public MongoDatabaseVerifier(MongoClient mongoClient) {
        checkConnectionOrThrow(mongoClient);
    }

    /**
     * Calls {@link MongoClient#getAddress()} and throws the result away if successful 
     * @param client
     */
    void checkConnectionOrThrow(MongoClient client) { 
        client.getAddress(); // this will either succeed super fast or explode
        log.info("Database fully started ...");
    }
}

Поскольку этот компонент выполняет проверку при создании, Spring продолжит запуск только в случае успеха. В противном случае будет выдано исключение создания компонента, и запуск будет прерван.

Надеюсь, это поможет

person pandaadb    schedule 17.05.2019
comment
Спасибо. Это хороший способ решить эту проблему. Но я надеялся, что есть более простой способ добиться этого????. - person Stanislav Serdiuk; 18.05.2019
comment
Теоретически есть. Причина, по которой он не прерывается, заключается в классе DefaultServerMonitor и асинхронном характере его проверок. Любой сбойный код, который вы выполняете в потоке создания spring при запуске, прервет приложение. Монитор не предназначен для прерывания чего-либо, он просто управляет соединениями. - person pandaadb; 20.05.2019

Я попытался воспроизвести проблему. Хотя он говорит, что приложение запущено, но оно прерывается после ожидания периода ожидания в 30000 мс настроек для подключения к кластеру.

Как указывали другие, вы можете написать некоторую пользовательскую логику для проверки подключения или попытаться установить уменьшение тайм-аута подключения для быстрого сбоя.

пример кода проекта

2019-05-20 10:28:07.381  INFO 86945 --- [  restartedMain] com.demo.Application                     : Started Application in 5.882 seconds (JVM running for 6.893)
2019-05-20 10:28:07.435  INFO 86945 --- [  restartedMain] org.mongodb.driver.cluster               : Cluster description not yet available. Waiting for 30000 ms before timing out
2019-05-20 10:28:26.253  INFO 86945 --- [oogle.com:27017] org.mongodb.driver.cluster               : Exception in monitor thread while connecting to server www.google.com:27017

com.mongodb.MongoSocketOpenException: Exception opening socket
    at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:67) ~[mongodb-driver-core-3.8.2.jar:na]
    at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:126) ~[mongodb-driver-core-3.8.2.jar:na]
    at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:117) ~[mongodb-driver-core-3.8.2.jar:na]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]
Caused by: java.net.SocketTimeoutException: connect timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_101]
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_101]
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_101]
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_101]
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_101]
    at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_101]
    at com.mongodb.internal.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:64) ~[mongodb-driver-core-3.8.2.jar:na]
    at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:62) ~[mongodb-driver-core-3.8.2.jar:na]
    ... 3 common frames omitted

2019-05-20 10:28:37.444  INFO 86945 --- [  restartedMain] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-05-20 10:28:37.452 ERROR 86945 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:816) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:797) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:324) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at com.demo.Application.main(Application.java:12) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_101]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.1.3.RELEASE.jar:2.1.3.RELEASE]
Caused by: org.springframework.dao.DataAccessResourceFailureException: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {type=UNKNOWN, servers=[{address=www.google.com:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.SocketTimeoutException: connect timed out}}]; nested exception is com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {type=UNKNOWN, servers=[{address=www.google.com:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.SocketTimeoutException: connect timed out}}]
    at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:90) ~[spring-data-mongodb-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2774) ~[spring-data-mongodb-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:2629) ~[spring-data-mongodb-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:2353) ~[spring-data-mongodb-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.mongodb.core.MongoTemplate.findById(MongoTemplate.java:843) ~[spring-data-mongodb-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.findById(SimpleMongoRepository.java:118) ~[spring-data-mongodb-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_101]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
    at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:359) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:644) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:608) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at com.sun.proxy.$Proxy61.findById(Unknown Source) ~[na:na]
    at com.demo.TestConfig.lambda$commandLineRunner$0(TestConfig.java:15) ~[classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:813) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    ... 10 common frames omitted
Caused by: com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {type=UNKNOWN, servers=[{address=www.google.com:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.SocketTimeoutException: connect timed out}}]
    at com.mongodb.internal.connection.BaseCluster.getDescription(BaseCluster.java:179) ~[mongodb-driver-core-3.8.2.jar:na]
    at com.mongodb.internal.connection.MultiServerCluster.getDescription(MultiServerCluster.java:54) ~[mongodb-driver-core-3.8.2.jar:na]
    at com.mongodb.client.internal.MongoClientDelegate.getConnectedClusterDescription(MongoClientDelegate.java:136) ~[mongodb-driver-3.8.2.jar:na]
    at com.mongodb.client.internal.MongoClientDelegate.createClientSession(MongoClientDelegate.java:94) ~[mongodb-driver-3.8.2.jar:na]
    at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.getClientSession(MongoClientDelegate.java:249) ~[mongodb-driver-3.8.2.jar:na]
    at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:172) ~[mongodb-driver-3.8.2.jar:na]
    at com.mongodb.client.internal.FindIterableImpl.first(FindIterableImpl.java:198) ~[mongodb-driver-3.8.2.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2813) ~[spring-data-mongodb-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2788) ~[spring-data-mongodb-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:2626) ~[spring-data-mongodb-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    ... 35 common frames omitted

2019-05-20 10:28:37.457  INFO 86945 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

Process finished with exit code 0
person Barath    schedule 20.05.2019
comment
Спасибо. Это работает. Я полагаю, мне нужно написать некоторую логику для проверки подключения. - person Stanislav Serdiuk; 20.05.2019
comment
Я нашел случай, когда даже с TimeOut приложение не прерывается. Когда я использую планировщик в приложении, он продолжает работать нормально, выполняет запланированное задание и каждый раз получает TimeOut. Конечно, я могу установить его в блоке try/catch, но это не очень хорошо для меня, и только добавление bean-компонента с проверкой соединения помогает мне прервать приложение. - person Stanislav Serdiuk; 20.05.2019