I am trying to use MongoDB Atlas M0 (Free Tier) for my JAVA EE application, now I am using:
Local MongoDB database (v4.0.4)
Hibernate Core "hibernate-core 5.3.6.Final"
Hibernate OGM "hibernate-ogm-mongodb 5.3.1.Final"
Java application server WildFly 15.0.0.Final.
With a local database a pair MongoDB and Hibernate OGM works like a charm, but when I tried to connect Hibernate with Mongo Atlas on free tier to test cloud database, I am was not able to have a working connection, because mongodb driver throws an exception com.mongodb.MongoSocketReadException: Prematurely reached end of stream
I will provide two versions of my persistence.xml, first is working fine with localhost and second is what I used to connect to cloud.
working localhost version:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
version="2.2">
<!-- @@@ MongoDB HIBERNATE OGM PERSISTENCE UNIT @@@ -->
<persistence-unit name="PersistenceUnitNoSQL" transaction-type="JTA">
<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
<class>org.companyname.model.UserEntity</class>
<class>org.companyname.model.ItemEntity</class>
<properties>
<property name="hibernate.ogm.datastore.provider" value="mongodb"/>
<property name="hibernate.ogm.datastore.host" value="localhost:27017"/>
<property name="hibernate.ogm.datastore.database" value="databasename"/>
<property name="hibernate.ogm.datastore.create_database" value="true"/>
</properties>
</persistence-unit>
</persistence>
not working atlas cloud version:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
version="2.2">
<!-- @@@ MongoDB HIBERNATE OGM PERSISTENCE UNIT @@@ -->
<persistence-unit name="PersistenceUnitNoSQL" transaction-type="JTA">
<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
<class>org.companyname.model.UserEntity</class>
<class>org.companyname.model.ItemEntity</class>
<properties>
<property name="hibernate.ogm.datastore.provider" value="mongodb"/>
<property name="hibernate.ogm.datastore.host" value="cluster0-clustername-shard-00-00-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-01-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017"/>
<property name="hibernate.ogm.datastore.database" value="databasename"/>
<property name="hibernate.ogm.datastore.create_database" value="true"/>
<property name="hibernate.ogm.datastore.username" value="atlas-user-name"/>
<property name="hibernate.ogm.datastore.password" value="atlas-user-password"/>
<property name="hibernate.ogm.mongodb.authentication_mechanism" value="SCRAM_SHA_1"/>
</properties>
</persistence-unit>
</persistence>
Like a host I used replica sets URIs from "standard connection string" from helping window in the Atlas account, because with "short SRV connection string" Hibernate throws org.hibernate.service.spi.ServiceException: OGM000072: Unable to configure datastore provider, so I think there is no support of this type of connection yet.
So with this last persistence.xml configuration I had following error:
20:02:01,094 INFO [org.mongodb.driver.cluster] (ServerService Thread Pool -- 78) Cluster description not yet available. Waiting for 30000 ms before timing out
20:02:01,175 INFO [org.mongodb.driver.cluster] (cluster-ClusterId{value='5c5497a97aea6111622c7540', description='null'}-cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017)
Exception in monitor thread while connecting to server cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017: com.mongodb.MongoSocketReadException: Prematurely reached end of stream
at com.mongodb.internal.connection.SocketStream.read(SocketStream.java:112)
at com.mongodb.internal.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:570)
at com.mongodb.internal.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:441)
at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:295)
at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:255)
at com.mongodb.internal.connection.CommandHelper.sendAndReceive(CommandHelper.java:83)
at com.mongodb.internal.connection.CommandHelper.executeCommand(CommandHelper.java:33)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:106)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:63)
at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:127)
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:117)
at java.lang.Thread.run(Thread.java:748)
Hibernate tries to connect to each shard (00-00, 00-01, 00-02), but with all throws this exception.
What I tried to do to fix the problem:
using mongo-java-driver version 3.9.1 instead of Hibernate 3.6.3 built-in, but both drivers work with the same problem
my IP is added (my app is deployed from my laptop) to my atlas account IP Whitelist
I am able to connect fine to cluster from Mongo Shell and MongoDB Compass
I had a doubts about "hibernate.ogm.mongodb.authentication_mechanism", but "SCRAM_SHA_1" and "BEST" didn't worked for me
and finally I tried to make a connection to the cluster from Java directly (without Hibernate)
with
MongoClient mongoClient = MongoClients.create("mongodb+srv://atlas-user-name:atlas-user-password@cluster0-clustername-raa4n.mongodb.net/test?retryWrites=true");
or
MongoClient mongoClient = MongoClients.create("mongodb://atlas-user-name:atlas-user-password@cluster0-clustername-shard-00-00-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-01-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-clustername-shard-0&authSource=admin&retryWrites=true");
and both cases worked fine, I was able to make a connection and to use the database without problems.
So my problem is why Hibernate throws this kind of exception?