Spring Boot で MongoDB をつかってみる
NoSQL 触ったことがなかったので、 Spring Boot で MongoDB を使用してみます。
まずは、ローカル開発は Docker でやるために、Mongo のコンテナを起動します。
というかこの点に関してハマった点をまとめるエントリーです。
まずは、root user および admin database をセットアップせずに起動し、
Application から疎通するために必要な流れをみていきます。
- docker-compose.yaml
- MongoDB と mongo-express を記載
- 初期DBを指定
- この DB にコレクション(RDBでいう Table のようなイメージ)を作る必要あり
version: '3.1' services: mongo: container_name: spring-mongo image: mongo:4.2 restart: always environment: MONGO_INITDB_DATABASE: spring-mongo ports: - 27017:27017 volumes: - ./mongo:/data/db - ./mongo/init:/docker-entrypoint-initdb.d mongo-express: container_name: spring-mongo-express image: mongo-express restart: always ports: - 9080:8081 # コンテナの 8081 にマッピングしていればホスト側は任意 depends_on: - mongo
- application.yaml
spring: data: mongodb: # port: 27017 # if you set not default port host: localhost database: spring-mongo username: demo password: 1qazxsw2
host,database,username,password の記載は uri: mongodb://localhost/spring-mongo
とすることも可能です。
ここで指定している username,password はどこで設定したかというと、
image: mongo:4.2
の ENTRYPOINT である、 docker-entrypoint.sh にて実行される .js か .sh ファイル にて流し込んでいます。
$ ls -1 mongo/init 01_import_init_data.json 01_import_init_data.sh 02_create_user.js
let user = { user: 'demo', pwd: '1qazxsw2', roles: [{ role: 'readWrite', db: 'spring-mongo' }] }; db.createUser(user);
これで、 docker-compose up -d
をすると、
- spring-mongo という DB がつくられ( 指定しなかったら test という名前でつくられる )
- user(demo) が作成され
- コレクションやドキュメントを登録していれば
Application の接続先が準備できます。
MongoDB に繋いで確認してみます。 DB,Collection,Document が作成されています。
docker-compose exec mongo bash mongo > show dbs admin 0.000GB config 0.000GB local 0.000GB spring-mongo 0.000GB > use spring-mongo switched to db spring-mongo > show collections customer > db.customer.find() { "_id" : ObjectId("6024e6a39c82f64f379738ca"), "firstName" : "Mike", "lastName" : "Popcorn", "_class" : "com.kiyotakeshi.spring.mongo.Customer" } { "_id" : ObjectId("6024e6a39c82f64f379738cb"), "firstName" : "Sam", "lastName" : "Smith", "_class" : "com.kiyotakeshi.spring.mongo.Customer" }
これらを接続先として、 application.yaml で指定していたわけです。
あとは、アプリを起動すると...
./mvnw spring-boot:run
MongoDB につなぎこみ、検索できています。
※このアプリの実装はほぼ 参考 記載の Spring のガイドのままです
------------------------------ Customers found with findAll() 2021-02-14 13:30:26.807 INFO 6466 --- [ main] org.mongodb.driver.connection : Opened connection [connectionId{localValue:3, serverValue:12}] to localhost:27017 Customer{id='6024e6a39c82f64f379738ca', firstName='Mike', lastName='Popcorn'} Customer{id='6024e6a39c82f64f379738cb', firstName='Sam', lastName='Smith'} -------------------------------- Customer found with findByFirstName('Alice'): null -------------------------------- Customers found with findByLastName('Smith'): Customer{id='6024e6a39c82f64f379738cb', firstName='Sam', lastName='Smith'} 2021-02-14 13:30:26.848 INFO 6466 --- [extShutdownHook] org.mongodb.driver.connection : Closed connection [connectionId{localValue:3, serverValue:12}] to localhost:27017 because the pool has been closed. Process finished with exit code 0
root user および admin database をセットアップした場合
以下おまけ。
docker-compose に以下のような記載をしているものを見かけました。
# mongodb MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: 1qazxsw2 # mongo-express environment: ME_CONFIG_MONGODB_ADMINUSERNAME: root ME_CONFIG_MONGODB_ADMINPASSWORD: 1qazxsw2
これらは、
- root user および admin database をセットアップ
- セットアップされていた場合の mongo-express から接続するための設定
をしている箇所で、この設定を有効にしている場合、 Application の接続時の設定も変更する必要がありました。
先ほどの設定で、そのままアプリを起動するとコネクション時に認証エラーに。
Caused by: org.springframework.data.mongodb.UncategorizedMongoDbException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='demo', source='spring-mongo', password=<hidden>, mechanismProperties=<hidden>}; nested exception is com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='demo', source='spring-mongo', password=<hidden>, mechanismProperties=<hidden>} Caused by: com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='demo', source='spring-mongo', password=<hidden>, mechanismProperties=<hidden>} Caused by: com.mongodb.MongoCommandException: Command failed with error 18 (AuthenticationFailed): 'Authentication failed.' on server localhost:27017. The full response is {"ok": 0.0, "errmsg": "Authentication failed.", "code": 18, "codeName": "AuthenticationFailed"} 2021-02-14 13:42:18.968 INFO 6735 --- [ main] org.mongodb.driver.connection : Closed connection [connectionId{localValue:4}] to localhost:27017 because there was a socket exception raised by this connection.
以下のように、 application.yaml に authentication-database と接続情報を記載する必要があります。
host: localhost database: spring-mongo username: root # if you set "MONGO_INITDB_ROOT_USERNAME", change that username password: 1qazxsw2 # if you set "MONGO_INITDB_ROOT_*", in docker-compose authentication-database: admin # host,database,username,password の記載を一行にまとめる場合 # uri: mongodb://root:1qazxsw2@localhost/spring-mongo?authSource=admin
これで無事にコネクションできます。