Unable to connect to CosmosDb Mongo Api from SpringBoot Application - mongodb

Trying to connect to cosmosdb Mongo API using Primary Connection String and UserName(Database Name)
Caused by: com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches com.mongodb.client.internal.MongoClientDelegate$1#3c291aad. Client view of cluster state is {type=REPLICA_SET, servers=[{address=**********.documents.azure.com:10255, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketWriteException: Exception sending message}, caused by {java.net.SocketException: Connection reset}}]
at com.mongodb.internal.connection.BaseCluster.createTimeoutException(BaseCluster.java:401) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:120) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.MultiServerCluster.selectServer(MultiServerCluster.java:54) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.client.internal.MongoClientDelegate.getConnectedClusterDescription(MongoClientDelegate.java:138) ~[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:190) ~[mongodb-driver-3.8.2.jar:na]
at com.mongodb.client.internal.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:960) ~[mongodb-driver-3.8.2.jar:na]
at com.mongodb.client.internal.MongoCollectionImpl.executeDelete(MongoCollectionImpl.java:940) ~[mongodb-driver-3.8.2.jar:na]
at com.mongodb.client.internal.MongoCollectionImpl.deleteMany(MongoCollectionImpl.java:551) ~[mongodb-driver-3.8.2.jar:na]
at org.springframework.data.mongodb.core.MongoTemplate$9.doInCollection(MongoTemplate.java:1729) ~[spring-data-mongodb-2.1.9.RELEASE.jar:2.1.9.RELEASE]
at org.springframework.data.mongodb.core.MongoTemplate$9.doInCollection(MongoTemplate.java:1689) ~[spring-data-mongodb-2.1.9.RELEASE.jar:2.1.9.RELEASE]
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:545) ~[spring-data-mongodb-2.1.9.RELEASE.jar:2.1.9.RELEASE]
... 30 common frames omitted

Please follow the example github project in the link below and you will be able to connect.
https://github.com/Azure-Samples/azure-cosmos-db-mongodb-spring

Try with MongoDB driver 3.7.1 or earlier.
It appears that’s there’s an issue with MongoDB driver for Java 3.8.0 and above and the way Cosmos DB takes the MongoDB protocol.

Related

com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {type=UNKNOWN, servers=[]

We are trying to connect to Mongo Atlas from Java code using
URI "mongodb+srv::#serveraddress/dbname?retryWrites=true&w=1" but getting MongoTimeoutException exception.
Strange thing here is in exception trace servers=[] list is empty.
What could be the possible reasons for this error?
MongoDB Server and Java Driver Details:
MongoDB Server: 4.2
MongoDB java Driver: 3.12.5
spring-data-mongodb: 2.1.5.RELEASE
Please let me know if any further information needed.
Thank you for the help.
com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {type=UNKNOWN, servers=[]
at com.mongodb.internal.connection.BaseCluster.getDescription(BaseCluster.java:182)
at com.mongodb.internal.connection.AbstractMultiServerCluster.getDescription(AbstractMultiServerCluster.java:54)
at com.mongodb.client.internal.MongoClientDelegate.getConnectedClusterDescription(MongoClientDelegate.java:152)
at com.mongodb.client.internal.MongoClientDelegate.createClientSession(MongoClientDelegate.java:103)
at com.mongodb.Mongo.createClientSession(Mongo.java:832)
at com.mongodb.MongoClient.startSession(MongoClient.java:582)
at com.mongodb.MongoClient.startSession(MongoClient.java:569)
at com.shutterfly.services.project.InitMongoDBCollection.onApplicationEvent(InitMongoDBCollection.java:36)
at com.shutterfly.services.project.InitMongoDBCollection.onApplicationEvent(InitMongoDBCollection.java:20)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
at org.springframework.boot.context.event.EventPublishingRunListener.running(EventPublishingRunListener.java:105)
at org.springframework.boot.SpringApplicationRunListeners.running(SpringApplicationRunListeners.java:78)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:332)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
at com.shutterfly.services.project.Application.main(Application.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:748)
Adding the answer so that it should be helpful for others, who might see similar issue in future.
We have resolved this issue, The problem was it was taking time to find the list of clusters and connect to that with default time, we can use "MongoClientOptionsFactoryBean" to customised the parameters and can override the default configuration.
#Bean
public MongoClientOptionsFactoryBean getMongoClientOptionsFactoryBean() {
MongoClientOptionsFactoryBean mongoClientOptionsFactoryBean = new MongoClientOptionsFactoryBean();
mongoClientOptionsFactoryBean.setConnectTimeout(timeout);
mongoClientOptionsFactoryBean.setConnectionsPerHost(connectionsPerHost);
mongoClientOptionsFactoryBean.setMaxWaitTime(maxWaitTime);
mongoClientOptionsFactoryBean.setServerSelectionTimeout(ServerSelectionTimeout);
mongoClientOptionsFactoryBean.setThreadsAllowedToBlockForConnectionMultiplier(connMultiplier);
return mongoClientOptionsFactoryBean;
}
in my case mongo was simply not running :)
please, check it with:
systemctl status mongod.service
and make sure it is enabled before rebooting the server:
systemctl enable mongod.service
so I have same problem
I fix it by this code
use this import
import com.mongodb.client.MongoClient;
and this is the code
String web="mongodb://";
MongoClient mongoClient = MongoClients.create(web+ENVIRONMENT);
database = mongoClient.getDatabase("PUT_HERE_YOUR_DB_NAME");
MAYBE in some place you will need change the web
String web="mongodb+srv://"

How to connect Mongodb Atlas to Spring

I have a web application which is using Spring Boot to handle the backend logics. I'm trying to integrate mongodb to track some information about the users of this webapp.
I created a database on mongodb Atlas and through the Mongo Shell the connection goes fine. The problem comes when I try to connect with Spring. Let me show you all the details
Inside Atlas, I added this IP Address (0.0.0.0/0 (includes your current IP address)) into Security > Network Address. In theory this should allow me to connect to the database from any IP address.
I then created a collection called "test".
If I click on my cluster and then on the connect button, it ask me with which modality I want to connect. I choose "Connect your application", and then I have to select the Driver and the Version. I choose respectively "Java" and "3.6 or later" (I'm not sure if it's the correct version, the alternatives are 3.4 or 3.3). And finally it shows me the connection string which is:
mongodb+srv://admin:<password>#umadit-obxpb.mongodb.net/test?retryWrites=true&w=majority
To connect to Atlas with Spring I'm using this dependency
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
Inside the application.properties file I have these two lines to configure mongo.
spring.data.mongodb.host=mongodb+srv://admin:<password>#umadit-obxpb.mongodb.net/test?retryWrites=true&w=majority
spring.data.mongodb.port=27017
Instead of the password I put for obvious reasons.
The only problem is that when I start Spring Boot I continue to receive this error message:
2020-02-25 16:31:25.605 INFO 41162 --- [=majority:27017] org.mongodb.driver.cluster : Exception in monitor thread while connecting to server mongodb+srv://admin:<password>#umadit-obxpb.mongodb.net/test?retrywrites=true&w=majority:27017
com.mongodb.MongoSocketException: mongodb+srv://admin:<password>#umadit-obxpb.mongodb.net/test?retrywrites=true&w=majority: nodename nor servname provided, or not known
at com.mongodb.ServerAddress.getSocketAddress(ServerAddress.java:188) ~[mongo-java-driver-3.6.4.jar:na]
at com.mongodb.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:59) ~[mongo-java-driver-3.6.4.jar:na]
at com.mongodb.connection.SocketStream.open(SocketStream.java:57) ~[mongo-java-driver-3.6.4.jar:na]
at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:126) ~[mongo-java-driver-3.6.4.jar:na]
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:114) ~[mongo-java-driver-3.6.4.jar:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]
Caused by: java.net.UnknownHostException: mongodb+srv://admin:<password>#umadit-obxpb.mongodb.net/test?retrywrites=true&w=majority: nodename nor servname provided, or not known
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method) ~[na:1.8.0_111]
at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928) ~[na:1.8.0_111]
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323) ~[na:1.8.0_111]
at java.net.InetAddress.getAllByName0(InetAddress.java:1276) ~[na:1.8.0_111]
at java.net.InetAddress.getAllByName(InetAddress.java:1192) ~[na:1.8.0_111]
at java.net.InetAddress.getAllByName(InetAddress.java:1126) ~[na:1.8.0_111]
at java.net.InetAddress.getByName(InetAddress.java:1076) ~[na:1.8.0_111]
at com.mongodb.ServerAddress.getSocketAddress(ServerAddress.java:186) ~[mongo-java-driver-3.6.4.jar:na]
... 5 common frames omitted
I don't know what to do in order to make it work. Am I missing something?
SOLUTION
As #barrypicker suggested, the problem was inside the properties file. Instead of using spring.data.mongodb.host I used spring.data.mongodb.uri. Now it works perfectly.
spring.data.mongodb.uri=mongodb+srv://admin:<password>#umadit-obxpb.mongodb.net/test?retryWrites=true&w=majority
even without spring.data.mongodb.port
Well, I think your to connect to Mongo Atlas your application.properties should have spring.data.mongodb.uri instead of spring.data.mongodb.host.spring.data.mongodb.uri: mongodb://<user>:<passwd>#<host>:<port>/<dbname>
I think this may work
`
Another issue with the atlas is that your IP is not allowed, make sure you add your IP at the network access tab.
Use this dependency inside "pom.xml" file
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
Inside the "application.properties"
use "spring.data.mongodb.uri"
spring.data.mongodb.uri = mongodb+srv://<user>:<password>#<cluster_name>.mogodb.net/<dbname>

Springboot HikariCP

I using springboot with HikariCP, but after a while my app crash and I got the error:
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
...
Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
....
Caused by: java.sql.SQLTransientConnectionException: HikariPool-6 - Connection is not available, request timed out after 30000ms.
This is my aplication.properties
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.url=jdbc:postgresql://localhost:5432/db_dnaso
#spring.datasource.url=jdbc:postgresql://172.16.1.10:5432/db_dnaso
spring.datasource.username=postgres
spring.datasource.password=dna44100
spring.datasource.driver-class-name=org.postgresql.Driver
So I have a lot of save, find and anothers access to DB, how can I visualize how method are blocking my connection?
tks
It looks like your your database server is running out of connection. Default value for property maximumPoolSize in Hikari is 10. That means it will try to create 10 connection on server startup and it will not start if not able to acquire 10 connection or may fail if your db server pool size having less connection in the pool as you are creating using Hikari configuration.
If you are able to start Spring Boot server and then facing this issue then try enabling leakDetectionThreshold and check which connection is taking more time and not returning to Hikari pool .
spring:
datasource:
hikari:
leak-detection-threshold: 2000
Enable the leakDetectionThreshold, set to something like 1 minute (60000ms). It is likely that you have a connection leak somewhere ... a connection is borrowed but never closed (returned).
In springboot, you can set spring.datasource.hikari.leak-detection-threshold=10000 (in milliseconds) in application.properties.
And the default value for maximumPoolSize is 10. You can change it with spring.datasource.hikari.maximum-pool-size=xx.

Spring Boot MongoDB with shared Domain Object

I have 3 services(3 different projects eg ClientService, AggregationService, DataService) that share same domain object and only one of them(DataService) connects to MongoDB and sends back the data to other 2 services.
All these services are spring boot based
When I was keeping separate java file of the domain object kept in the respective project then it all worked fine as the domain object in ClientService and AggregationService didn't have mongodb annotations eg #Document, #Field.
But when I kept the domain object in a common module so that i don't have to maintain 3 copies, ClientService and AggregationService started throwing exception during start up. Though these services do start up and returns the response correctly but the exception also comes up when these services start up.
Below is the domain object:
#Document(collection = "transformed_categories")
public class Category extends ResourceSupport {
#Field("id")
private String customId;
private String name;
private String type;
}
Exception:
2017-02-27 15:10:41.098 INFO 9052 --- [ main] c.c.delivery.CleintServiceApplication : Started CleintServiceApplication in 3.47 seconds (JVM running for 3.918)
2017-02-27 15:10:41.895 INFO 9052 --- [localhost:27017] org.mongodb.driver.cluster : Exception in monitor thread while connecting to server localhost:27017
com.mongodb.MongoSocketOpenException: Exception opening socket
at com.mongodb.connection.SocketStream.open(SocketStream.java:63) ~[mongo-java-driver-3.4.1.jar:na]
at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:115) ~[mongo-java-driver-3.4.1.jar:na]
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:113) ~[mongo-java-driver-3.4.1.jar:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[na:1.8.0_05]
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) ~[na:1.8.0_05]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345) ~[na:1.8.0_05]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_05]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_05]
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_05]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_05]
at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_05]
at com.mongodb.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:57) ~[mongo-java-driver-3.4.1.jar:na]
at com.mongodb.connection.SocketStream.open(SocketStream.java:58) ~[mongo-java-driver-3.4.1.jar:na]
... 3 common frames omitted
I found the exact place which is causing the issue.
The issue is caused by maven dependency that I added into my common-library project where I intend to keep all my domain objects.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.10.0.RELEASE</version>
</dependency>
If I remove this dependency then the exception doesn't come. What should be the approach in keeping domain objects which are shared across the projects?
This is an old post but requires answers.
First thing, Microservices should not be sharing code. When there are domain objects which need to be sent across, we should use DTO pattern which should be owned by every microservice and that code should not be shared across. This is a recommended practice.
Coming to MongoDB exception, this is a normal behavior of a spring boot application. When it sees MongoDB in the class path and no configuration in properties file, it would look for a MongoDB instance at localhost:27017
So if we don't intend to connect to MongoDB from a Microservice then MogoDB driver should not be present in the class path.

MongoDB: PLAIN method not suported

I'm getting this message when I'm trying to deploy my war artifact. My app is using hibernate ogm and it's trying to build persistence context when it's deployed. The message I'm getting is:
org.hibernate.service.spi.ServiceException: OGM000071: Unable to start datatore provider Caused by: org.hibernate.service.spi.ServiceException: OGM000071: Unable to start datatore provider Caused by: org.hibernate.HibernateException: OGM001214: Unable to connect to MongoDB instance: Timed out after 30000 ms while waiting for a server that matches ReadPreferenceServerSelector{readPreference=primary}. Client view of cluster state is {type=UNKNOWN, servers=[{address=mongo:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=PLAIN, userName='living', source='lvdb', password=, mechanismProperties={}}}, caused by {com.mongodb.MongoCommandException: Command failed with error 2: 'Unsupported mechanism PLAIN' on server mongo:27017. The full response is { \"supportedMechanisms\" : [\"MONGODB-CR\", \"MONGODB-X509\", \"SCRAM-SHA-1\"], \"ok\" : 0.0, \"errmsg\" : \"Unsupported mechanism PLAIN\", \"code\" : 2, \"codeName\" : \"BadValue\" }}}] Caused by: com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches ReadPreferenceServerSelector{readPreference=primary}. Client view of cluster state is {type=UNKNOWN, servers=[{address=mongo:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=PLAIN, userName='living', source='lvdb', password=, mechanismProperties={}}}, caused by {com.mongodb.MongoCommandException: Command failed with error 2: 'Unsupported mechanism PLAIN' on server mongo:27017. The full response is { \"supportedMechanisms\" : [\"MONGODB-CR\", \"MONGODB-X509\", \"SCRAM-SHA-1\"], \"ok\" : 0.0, \"errmsg\" : \"Unsupported mechanism PLAIN\", \"code\" : 2, \"codeName\" : \"BadValue\" }}}]"}}
What do I need to do in order to use the other mechanisms?
You'd have to specificy the property hibernate.ogm.mongodb.authentication_mechanism (see here).
Which is the authentication mechanism you'd want to use? We may not support it yet, but if you let us know about your preference, we can try and look into making it work quickly.
For MongoDB, default supported mechanism is 'SCRAM-SHA-1'. So, while connecting, you need to specify this mechanism. I saw the same error when connecting to MongoDB through spring-data. While I didn't make any special configuration for mongo, first and obvious option for me to try was PLAIN mechanism for authentication. Finally, resolved it using SCRAM-SHA-1.
For Spring-data, code looked something like this:
MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(mongoUser, mongoDB, mongoPass.toCharArray());
Hope this helps.