Since I accessed Azure CosmosDB (MongoDB core) using Spring Boot, it is a record.
I was lazy to write the code, so I referred to https://spring.pleiades.io/guides/gs/accessing-data-mongodb/.
First, git clone the sample code normally.
$ git clone https://github.com/spring-guides/gs-accessing-data-mongodb.git
Set up MongoDB locally according to the tutorial,
$ sudo apt install mongodb
$ mkdir -p data/db
$ mongod --dbpath=./data/db
Run in Gradle.
$ gradle bootRun
Welcome to Gradle 6.5.1!
Here are the highlights of this release:
- Experimental file-system watching
- Improved version ordering
- New samples
For more details see https://docs.gradle.org/6.5.1/release-notes.html
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :bootRun
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.0.RELEASE)
2020-07-02 03:12:00.912 INFO 32643 --- [ main] c.e.a.AccessingDataMongodbApplication : Starting AccessingDataMongodbApplication on DESKTOP-N9T4CN3 with PID 32643 (XXX/gs-accessing-data-mongodb/complete/build/classes/java/main started by XXX in XXX/gs-accessing-data-mongodb/complete)
2020-07-02 03:12:00.917 INFO 32643 --- [ main] c.e.a.AccessingDataMongodbApplication : No active profile set, falling back to default profiles: default
2020-07-02 03:12:01.274 INFO 32643 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2020-07-02 03:12:01.315 INFO 32643 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 36ms. Found 1 repository interfaces.
2020-07-02 03:12:01.589 INFO 32643 --- [ main] org.mongodb.driver.cluster : Cluster created with settings {hosts=[localhost:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
2020-07-02 03:12:01.674 INFO 32643 --- [localhost:27017] org.mongodb.driver.connection : Opened connection [connectionId{localValue:1, serverValue:1}] to localhost:27017
2020-07-02 03:12:01.678 INFO 32643 --- [localhost:27017] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=localhost:27017, type=STANDALONE, state=CONNECTED, ok=true, version=ServerVersion{versionList=[3, 6, 8]}, minWireVersion=0, maxWireVersion=6, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=2881100}
2020-07-02 03:12:01.745 WARN 32643 --- [ main] o.s.data.convert.CustomConversions : Registering converter from class java.time.LocalDateTime to class java.time.Instant as reading converter although it doesn't convert from a store-supported type! You might wanna check you annotation setup at the converter implementation.
2020-07-02 03:12:01.745 WARN 32643 --- [ main] o.s.data.convert.CustomConversions : Registering converter from class java.time.Instant to class java.time.LocalDateTime as reading converter although it doesn't convert from a store-supported type! You might wanna check you annotation setup at the converter implementation.
2020-07-02 03:12:01.771 WARN 32643 --- [ main] o.s.data.convert.CustomConversions : Registering converter from class java.time.LocalDateTime to class java.time.Instant as reading converter although it doesn't convert from a store-supported type! You might wanna check you annotation setup at the converter implementation.
2020-07-02 03:12:01.771 WARN 32643 --- [ main] o.s.data.convert.CustomConversions : Registering converter from class java.time.Instant to class java.time.LocalDateTime as reading converter although it doesn't convert from a store-supported type! You might wanna check you annotation setup at the converter implementation.
2020-07-02 03:12:02.134 INFO 32643 --- [ main] c.e.a.AccessingDataMongodbApplication : Started AccessingDataMongodbApplication in 1.552 seconds (JVM running for 1.853)
2020-07-02 03:12:02.157 INFO 32643 --- [ main] org.mongodb.driver.connection : Opened connection [connectionId{localValue:2, serverValue:2}] to localhost:27017
Customers found with findAll():
-------------------------------
Customer[id=5efcd1f2b15c223a7dc2a9ce, firstName='Alice', lastName='Smith']
Customer[id=5efcd1f2b15c223a7dc2a9cf, firstName='Bob', lastName='Smith']
Customer found with findByFirstName('Alice'):
--------------------------------
Customer[id=5efcd1f2b15c223a7dc2a9ce, firstName='Alice', lastName='Smith']
Customers found with findByLastName('Smith'):
--------------------------------
Customer[id=5efcd1f2b15c223a7dc2a9ce, firstName='Alice', lastName='Smith']
Customer[id=5efcd1f2b15c223a7dc2a9cf, firstName='Bob', lastName='Smith']
2020-07-02 03:12:02.270 INFO 32643 --- [extShutdownHook] org.mongodb.driver.connection : Closed connection [connectionId{localValue:2, serverValue:2}] to localhost:27017 because the pool has been closed.
BUILD SUCCESSFUL in 53s
2 actionable tasks: 2 executed
Take a peek inside with the mongo command.
$ mongo
MongoDB shell version v3.6.8
connecting to: mongodb://127.0.0.1:27017
Implicit session: session { "id" : UUID("2648d101-f236-4f56-bc3d-7250d32ef9a2") }
MongoDB server version: 3.6.8
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings:
2020-07-02T02:54:56.366+0900 I STORAGE [initandlisten]
2020-07-02T02:54:56.366+0900 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2020-07-02T02:54:56.366+0900 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten]
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten]
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten] ** WARNING: This server is bound to localhost.
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten] ** Remote systems will be unable to connect to this server.
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten] ** Start the server with --bind_ip <address> to specify which IP
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten] ** addresses it should serve responses from, or with --bind_ip_all to
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten] ** bind to all interfaces. If this behavior is desired, start the
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten] ** server with --bind_ip 127.0.0.1 to disable this warning.
2020-07-02T02:54:57.070+0900 I CONTROL [initandlisten]
2020-07-02T02:54:57.071+0900 I CONTROL [initandlisten]
2020-07-02T02:54:57.071+0900 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2020-07-02T02:54:57.071+0900 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2020-07-02T02:54:57.071+0900 I CONTROL [initandlisten]
> db.customer.find()
{ "_id" : ObjectId("5efcd1f2b15c223a7dc2a9ce"), "firstName" : "Alice", "lastName" : "Smith", "_class" : "com.example.accessingdatamongodb.Customer" }
{ "_id" : ObjectId("5efcd1f2b15c223a7dc2a9cf"), "firstName" : "Bob", "lastName" : "Smith", "_class" : "com.example.accessingdatamongodb.Customer" }
>
It's in.
At this point, the tutorial is not accessing the connected MongoDB. There are only two things related to data access implemented.
Customer.java
package com.example.accessingdatamongodb;
import org.springframework.data.annotation.Id;
public class Customer {
@Id
public String id;
public String firstName;
public String lastName;
public Customer() {}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format(
"Customer[id=%s, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
}
CustomerRepository.java
package com.example.accessingdatamongodb;
import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface CustomerRepository extends MongoRepository<Customer, String> {
public Customer findByFirstName(String firstName);
public List<Customer> findByLastName(String lastName);
}
It's very easy to implement because it uses the high-level API Repository. In fact, Spring Data MongoDB automatically generates a class that implements the CustomerRepojitory interface, and methods such as save and find are also available. It's convenient. (You can do more complicated things with the low-level API Template Mongo.)
This time, the main purpose is to access Cosmos DB created in MongoDB core, so we will use this sample using high level API.
Create Cosmos DB on the Azure side. This is created from crispy and portal by referring to https://docs.microsoft.com/ja-jp/azure/cosmos-db/create-mongodb-java#create-a-database-account. No need to create a collection.
Once created, check the URI of the connection destination from Portal. Since this time it is Java, copy the primary connection string displayed in the "Java" tab of "Quick Start".
Add main / resources / application.propertis to the sample code, add "spring.data.mongodb.uri", paste the value you copied earlier, and if Mongo DB Driver is 3.6 or later, add "& retrywrites" at the end. Add = false ". This is because Cosmos DB does not currently support Retryable Writes.
application.properties
spring.data.mongodb.uri=<your_connection_string>&retrywrites=false
Create a Configuration to use the defined URL.
CustomerRepogitoryConfig.java
package com.example.accessingdatamongodb;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CustomerRepositoryConfig {
@Value("${spring.data.mongodb.uri:mongodb://localhost:27017}")
public String connectionString;
public @Bean MongoClient mongoClient() {
return MongoClients.create(this.connectionString);
}
}
Run in Gradle.
$ gradle bootRun -Pargs=--debug
> Task :bootRun
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.0.RELEASE)
2020-07-02 04:54:56.451 INFO 3822 --- [ main] c.e.a.AccessingDataMongodbApplication : Starting AccessingDataMongodbApplication on DESKTOP-N9T4CN3 with PID 3822 (XXX/gs-accessing-data-mongodb/complete/build/classes/java/main started by XXX in XXX/gs-accessing-data-mongodb/complete)
2020-07-02 04:54:56.456 INFO 3822 --- [ main] c.e.a.AccessingDataMongodbApplication : No active profile set, falling back to default profiles: default
2020-07-02 04:54:57.370 INFO 3822 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2020-07-02 04:54:57.497 INFO 3822 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 118ms. Found 1 repository interfaces.
2020-07-02 04:54:58.011 INFO 3822 --- [ main] org.mongodb.driver.cluster : Cluster created with settings {hosts=[XXX:YYY], mode=MULTIPLE, requiredClusterType=REPLICA_SET, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500, requiredReplicaSetName='globaldb'}
2020-07-02 04:54:58.011 INFO 3822 --- [ main] org.mongodb.driver.cluster : Adding discovered server XXX:YYY to client view of cluster
2020-07-02 04:54:58.244 WARN 3822 --- [ main] o.s.data.convert.CustomConversions : Registering converter from class java.time.LocalDateTime to class java.time.Instant as reading converter although it doesn't convert from a store-supported type! You might wanna check you annotation setup at the converter implementation.
2020-07-02 04:54:58.245 WARN 3822 --- [ main] o.s.data.convert.CustomConversions : Registering converter from class java.time.Instant to class java.time.LocalDateTime as reading converter although it doesn't convert from a store-supported type! You might wanna check you annotation setup at the converter implementation.
2020-07-02 04:54:58.316 WARN 3822 --- [ main] o.s.data.convert.CustomConversions : Registering converter from class java.time.LocalDateTime to class java.time.Instant as reading converter although it doesn't convert from a store-supported type! You might wanna check you annotation setup at the converter implementation.
2020-07-02 04:54:58.317 WARN 3822 --- [ main] o.s.data.convert.CustomConversions : Registering converter from class java.time.Instant to class java.time.LocalDateTime as reading converter although it doesn't convert from a store-supported type! You might wanna check you annotation setup at the converter implementation.
2020-07-02 04:54:58.912 INFO 3822 --- [ main] c.e.a.AccessingDataMongodbApplication : Started AccessingDataMongodbApplication in 3.129 seconds (JVM running for 3.84)
2020-07-02 04:54:58.947 INFO 3822 --- [ main] org.mongodb.driver.cluster : No server chosen by com.mongodb.client.internal.MongoClientDelegate$1@210386e0 from cluster description ClusterDescription{type=REPLICA_SET, connectionMode=MULTIPLE, serverDescriptions=[ServerDescription{address=XXX:YYY, type=UNKNOWN, state=CONNECTING}]}. Waiting for 30000 ms before timing out
2020-07-02 04:54:59.082 INFO 3822 --- [azure.com:10255] org.mongodb.driver.connection : Opened connection [connectionId{localValue:1, serverValue:1162392059}] to XXX:YYY
2020-07-02 04:54:59.097 INFO 3822 --- [azure.com:10255] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=XXX:YYY, type=REPLICA_SET_PRIMARY, state=CONNECTED, ok=true, version=ServerVersion{versionList=[3, 6, 0]}, minWireVersion=0, maxWireVersion=6, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=12402600, setName='globaldb', canonicalAddress=XXX:YYY, hosts=[XXX:YYY], passives=[], arbiters=[], primary='XXX:YYY', tagSet=TagSet{[Tag{name='region', value='Japan East'}]}, electionId=null, setVersion=1, lastWriteDate=null, lastUpdateTimeNanos=134393982328436}
2020-07-02 04:54:59.100 INFO 3822 --- [azure.com:10255] org.mongodb.driver.cluster : Adding discovered server XXX:YYY to client view of cluster
2020-07-02 04:54:59.103 INFO 3822 --- [azure.com:10255] org.mongodb.driver.cluster : Server XXX:YYY is no longer a member of the replica set. Removing from client view of cluster.
2020-07-02 04:54:59.105 INFO 3822 --- [azure.com:10255] org.mongodb.driver.cluster : Canonical address XXX:YYY does not match server address. Removing XXX:YYY from client view of cluster
2020-07-02 04:54:59.338 INFO 3822 --- [azure.com:10255] org.mongodb.driver.connection : Opened connection [connectionId{localValue:2, serverValue:689958399}] to XXX:YYY
2020-07-02 04:54:59.348 INFO 3822 --- [azure.com:10255] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=XXX:YYY, type=REPLICA_SET_PRIMARY, state=CONNECTED, ok=true, version=ServerVersion{versionList=[3, 6, 0]}, minWireVersion=0, maxWireVersion=6, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=8755400, setName='globaldb', canonicalAddress=XXX:YYY, hosts=[XXX:YYY], passives=[], arbiters=[], primary='XXX:YYY', tagSet=TagSet{[Tag{name='region', value='Japan East'}]}, electionId=null, setVersion=1, lastWriteDate=null, lastUpdateTimeNanos=134394233832236}
2020-07-02 04:54:59.349 INFO 3822 --- [azure.com:10255] org.mongodb.driver.cluster : Setting max set version to 1 from replica set primary XXX:YYY
2020-07-02 04:54:59.349 INFO 3822 --- [azure.com:10255] org.mongodb.driver.cluster : Discovered replica set primary XXX:YYY
2020-07-02 04:54:59.603 INFO 3822 --- [ main] org.mongodb.driver.connection : Opened connection [connectionId{localValue:3, serverValue:1139365834}] to XXX:YYY
Customers found with findAll():
-------------------------------
Customer[id=5efcea13cac85c79009dba55, firstName='Alice', lastName='Smith']
Customer[id=5efcea15cac85c79009dba56, firstName='Bob', lastName='Smith']
Customer found with findByFirstName('Alice'):
--------------------------------
Customer[id=5efcea13cac85c79009dba55, firstName='Alice', lastName='Smith']
Customers found with findByLastName('Smith'):
--------------------------------
Customer[id=5efcea13cac85c79009dba55, firstName='Alice', lastName='Smith']
Customer[id=5efcea15cac85c79009dba56, firstName='Bob', lastName='Smith']
2020-07-02 04:55:01.231 INFO 3822 --- [extShutdownHook] org.mongodb.driver.connection : Closed connection [connectionId{localValue:3, serverValue:1139365834}] to XXX:YYY because the pool has been closed.
BUILD SUCCESSFUL in 8s
3 actionable tasks: 2 executed, 1 up-to-date
Succeeded. Let's verify that the customer collection has been added in the Data Explorer of the Azure portal.
You can see that the data has been created.
Cosmos DB has recently been offered Free Tier, so you can easily try out its features. Please feel it.
Recommended Posts