0

I am running a Spring-Boot project in IDEA Intelli for training that writes a recipe to the database using REST-full services. The IDE runs the server and I use Postman to query.

My problem is that the H2 database does not persist the data entered. In memory it's fine, but as soon as I shutdown and start up again, the data is gone.

Looking at the database file, I see a trace file that seems to show that the DB wasn't updated because there was a lock on it. I have searched for a lock file (locate *.lock.db), stopped all Java processes, and even rebooted without a change in behavior. I've changed the FILE_LOCK options for H2 but the problem persists.

EDIT: I just noticed that I hadn't tried FILE_LOCK=FILE. I just tried it and the db isn't updated. However, a trace file is not produced.

EDIT 2: I forgot to say that I'm running on Ubuntu 20.04.

EDIT 3: I am being careful to shutdown using the "actuator/shutdown" from Postman. Using file locking, I do this:

  • start the server running from my IDE. I can see the lock file being created
  • create a new recipe
  • make sure I can get it (returns the recipe, no error)
  • shutdown using the actuator. The lock file is removed.
  • startup the server again. New lock file.
  • try to get the recipe. Returns a 404 error. No trace file.

What could be causing this? Here is my trace.db file [note: when I use FILE_LOCK=FILE, no trace file is created, so maybe the locking problem was a red herring?]:

2021-09-09 07:54:08 database: flush
org.h2.message.DbException: General error: "java.lang.IllegalStateException: The file is locked: nio:/home/knute/IdeaProjects/recipes_db.mv.db [1.4.200/7]" [50000-200]
    at org.h2.message.DbException.get(DbException.java:194)
    at org.h2.message.DbException.convert(DbException.java:347)
    at org.h2.mvstore.db.MVTableEngine$1.uncaughtException(MVTableEngine.java:93)
    at org.h2.mvstore.MVStore.handleException(MVStore.java:2877)
    at org.h2.mvstore.MVStore.panic(MVStore.java:481)
    at org.h2.mvstore.MVStore.<init>(MVStore.java:402)
    at org.h2.mvstore.MVStore$Builder.open(MVStore.java:3579)
    at org.h2.mvstore.db.MVTableEngine$Store.open(MVTableEngine.java:170)
    at org.h2.mvstore.db.MVTableEngine.init(MVTableEngine.java:103)
    at org.h2.engine.Database.getPageStore(Database.java:2659)
    at org.h2.engine.Database.open(Database.java:675)
    at org.h2.engine.Database.openDatabase(Database.java:307)
    at org.h2.engine.Database.<init>(Database.java:301)
    at org.h2.engine.Engine.openSession(Engine.java:74)
    at org.h2.engine.Engine.openSession(Engine.java:192)
    at org.h2.engine.Engine.createSessionAndValidate(Engine.java:171)
    at org.h2.engine.Engine.createSession(Engine.java:166)
    at org.h2.engine.Engine.createSession(Engine.java:29)
    at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:340)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:173)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:152)
    at org.h2.Driver.connect(Driver.java:69)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358)
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206)
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:477)
    at com.zaxxer.hikari.pool.HikariPool.access$100(HikariPool.java:71)
    at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:725)
    at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:711)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "java.lang.IllegalStateException: The file is locked: nio:/home/knute/IdeaProjects/recipes_db.mv.db [1.4.200/7]" [50000-200]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:505)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)
    ... 33 more
Caused by: java.lang.IllegalStateException: The file is locked: nio:/home/knute/IdeaProjects/recipes_db.mv.db [1.4.200/7]
    at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:950)
    at org.h2.mvstore.FileStore.open(FileStore.java:166)
    at org.h2.mvstore.MVStore.<init>(MVStore.java:381)
    ... 27 more
Caused by: java.nio.channels.OverlappingFileLockException
    at java.base/sun.nio.ch.FileLockTable.checkList(FileLockTable.java:229)
    at java.base/sun.nio.ch.FileLockTable.add(FileLockTable.java:123)
    at java.base/sun.nio.ch.FileChannelImpl.tryLock(FileChannelImpl.java:1154)
    at org.h2.store.fs.FileNio.tryLock(FilePathNio.java:121)
    at java.base/java.nio.channels.FileChannel.tryLock(FileChannel.java:1165)
    at org.h2.mvstore.FileStore.open(FileStore.java:163)
    ... 28 more
2021-09-09 07:54:08 database: flush
org.h2.message.DbException: General error: "java.lang.IllegalStateException: The file is locked: nio:/home/knute/IdeaProjects/recipes_db.mv.db [1.4.200/7]" [50000-200]
    at org.h2.message.DbException.get(DbException.java:194)
    at org.h2.message.DbException.convert(DbException.java:347)
    at org.h2.mvstore.db.MVTableEngine$1.uncaughtException(MVTableEngine.java:93)
    at org.h2.mvstore.MVStore.handleException(MVStore.java:2877)
    at org.h2.mvstore.MVStore.panic(MVStore.java:481)
    at org.h2.mvstore.MVStore.<init>(MVStore.java:402)
    at org.h2.mvstore.MVStore$Builder.open(MVStore.java:3579)
    at org.h2.mvstore.db.MVTableEngine$Store.open(MVTableEngine.java:170)
    at org.h2.mvstore.db.MVTableEngine.init(MVTableEngine.java:103)
    at org.h2.engine.Database.getPageStore(Database.java:2659)
    at org.h2.engine.Database.open(Database.java:675)
    at org.h2.engine.Database.openDatabase(Database.java:307)
    at org.h2.engine.Database.<init>(Database.java:301)
    at org.h2.engine.Engine.openSession(Engine.java:74)
    at org.h2.engine.Engine.openSession(Engine.java:192)
    at org.h2.engine.Engine.createSessionAndValidate(Engine.java:171)
    at org.h2.engine.Engine.createSession(Engine.java:166)
    at org.h2.engine.Engine.createSession(Engine.java:29)
    at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:340)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:173)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:152)
    at org.h2.Driver.connect(Driver.java:69)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358)
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206)
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:477)
    at com.zaxxer.hikari.pool.HikariPool.access$100(HikariPool.java:71)
    at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:725)
    at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:711)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "java.lang.IllegalStateException: The file is locked: nio:/home/knute/IdeaProjects/recipes_db.mv.db [1.4.200/7]" [50000-200]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:505)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)
    ... 33 more
Caused by: java.lang.IllegalStateException: The file is locked: nio:/home/knute/IdeaProjects/recipes_db.mv.db [1.4.200/7]
    at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:950)
    at org.h2.mvstore.FileStore.open(FileStore.java:166)
    at org.h2.mvstore.MVStore.<init>(MVStore.java:381)
    ... 27 more
Caused by: java.nio.channels.OverlappingFileLockException
    at java.base/sun.nio.ch.FileLockTable.checkList(FileLockTable.java:229)
    at java.base/sun.nio.ch.FileLockTable.add(FileLockTable.java:123)
    at java.base/sun.nio.ch.FileChannelImpl.tryLock(FileChannelImpl.java:1154)
    at org.h2.store.fs.FileNio.tryLock(FilePathNio.java:121)
    at java.base/java.nio.channels.FileChannel.tryLock(FileChannel.java:1165)
    at org.h2.mvstore.FileStore.open(FileStore.java:163)
    ... 28 more

...and the application.properties file [note: in my current iteration, I am using FILE_LOCK=FILE]:

# Required by HyperSkill
server.port=8881
management.endpoints.web.exposure.include=*
management.endpoint.shutdown.enabled=true
spring.datasource.url=jdbc:h2:file:../recipes_db

# Solves file locking problem? No.
#spring.datasource.url=jdbc:h2:file:../recipes_db;DB_CLOSE_ON_EXIT=TRUE;FILE_LOCK=NO
#spring.datasource.url=jdbc:h2:file:../recipes_db;FILE_LOCK=NO
#spring.datasource.url=jdbc:h2:file:../recipes_db;FILE_LOCK=SOCKET
#spring.datasource.url=jdbc:h2:file:../recipes_db;FILE_LOCK=FS

# Needed?
spring.datasource.auto-commit=true

# To remove warning
spring.jpa.open-in-view=true
ksnortum
  • 2,809
  • 4
  • 27
  • 36
  • it may help you: https://github.com/h2database/h2database/issues/2152 – chachay Sep 09 '21 at 16:43
  • It seems that you don't shutdown your application gracefully (so lock files are not deleted), or h2 database doesn't have permissions to delete lock files on your OS. See more information here: https://stackoverflow.com/questions/9972372/what-is-the-proper-way-to-close-h2 – Mykhailo Skliar Sep 09 '21 at 18:49
  • I am being careful to shutdown with actuator/shutdown in Postman. See edit 3 above. – ksnortum Sep 09 '21 at 20:58

1 Answers1

0

I found the problem! Adding debug=true to the applications.properties file, I saw this:

Starting delayed evictData of schema as part of SessionFactory shut-down

So for some reason, Spring was explicitly dropping my table! Adding this to the applications.properties file stopped that:

spring.jpa.hibernate.ddl-auto=update
ksnortum
  • 2,809
  • 4
  • 27
  • 36