Skip to content

By default EmbeddedDb isn't closed in the end of context #7897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
artembilan opened this issue Jan 6, 2017 · 9 comments
Closed

By default EmbeddedDb isn't closed in the end of context #7897

artembilan opened this issue Jan 6, 2017 · 9 comments
Labels
status: superseded An issue that has been superseded by another theme: datasource Issues relating to data sources

Comments

@artembilan
Copy link
Member

When I build tests against EmbeddedDB (hsqldb), I noticed that in between @DirtiesContext that DB isn't closed:

Caused by: org.hsqldb.HsqlException: object name already exists: FOO

Looks like in the DataSourceAutoConfiguration

@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}

doesn't work because the next one PooledDataSourceConfiguration wins somehow.
And since spring-boot-starter-jdbc provides tomcat-jdbc by default, that feels like DataSourceConfiguration.Tomcat creates a DataSource bean.

Unlike EmbeddedDataSourceConfiguration that case doesn't provide this.database.shutdown(), therefore our in-memory DB stands in between @DirtiesContexts.

The simple app to demonstrate the issue: https://github.com/artembilan/EmbeddedDbDiritesContext

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 6, 2017
@wilkinsona
Copy link
Member

wilkinsona commented Jan 13, 2017

See #4699 which was for a similar problem with DevTools restarts

@dsyer
Copy link
Member

dsyer commented Jan 13, 2017

There are a couple of workarounds. One is to use an explicit URL for the data souce, e.g.

spring.datasource.url=jdbc:hsqldb:mem:test;shutdown=true

or for h2:

spring.datasource.url=jdbc:h2:mem:test

Another workaround is to use devtools (just put it on the classpath) because it automatically executes SHUTDOWN on the database when the context closes. Or use a migration tool (not the schema.sql initializer).

Also worth bearing in mind: use @Transactional instead of @DirtiesContext wherever you can.

@dsyer dsyer added priority: low type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 13, 2017
@artembilan
Copy link
Member Author

artembilan commented Jan 13, 2017

@SpringBootTest(properties = "spring.datasource.url=jdbc:h2:mem:test",

Does the trick for our tests.

But I still have to keep @DirtiesContext, because @Transactional doesn't help.
Although I don't see reason in it since I really would like to fully close DB in between test classes. That's why we use @DirtiesContext and try to rely on the database.shutdown().

Not sure that it is worth to play with Dev Tools in our case, but will keep it in mind.

Maybe some notes in the Reference Manual would be great?

Thank you!

artembilan added a commit to artembilan/jdbc that referenced this issue Jan 13, 2017
@dsyer dsyer added the type: documentation A documentation update label Jan 13, 2017
trisberg pushed a commit to spring-attic/jdbc that referenced this issue Feb 7, 2017
- Use `messages` as a default table name

- Fix JDBC test according Spring Boot 1.4 upgrade
  * Apply `@SpringBootTest` instead of deprecated functionality
  * Since `@SpringBootTest`s aren't mergeable in case of test classes hierarchy use `@TestPropertySource` for particular impl to accept its own properties
  * Resolve deprecations in the main classes according SCSt upgrade
  * Remove redundant `poller` usage in the Source definition since a default one is use implicitly any way
  Also see spring-attic/app-starters-release#28

- Use DB URL to force embedded usage and close it gracefully in case of `@DirtiesContext`
  See spring-projects/spring-boot#7897

Fixes: GH-1 (#1)
Fixes: GH-3 (#3)
@bclozel bclozel changed the title By default EmbeddedDb isn't closed in the end of contex By default EmbeddedDb isn't closed in the end of context Mar 21, 2018
@philwebb philwebb added this to the Icebox milestone Mar 21, 2018
@chrylis
Copy link
Contributor

chrylis commented Oct 30, 2018

I got a nasty case of "works on my machine" because of test order dependence. Spring 4.3, Boot 1.5, H2. I expected @DirtiesContext to resolve it (as it's explicitly documented for this situation), but no luck, and the recommended H2 JDBC URL does not help. (I'm explicitly printing log information from subsequent test cases, and they're seeing the dirty data.)

I am using Spock (spock-spring) with @DirtiesContext; is there a chance that's involved somehow? I see Spock examples using @DirtiesContext.

@wilkinsona
Copy link
Member

@chrylis It's hard to say without more context. If you'd like use to take a look, please provide a small sample that reproduces the behaviour you have described.

@62mkv
Copy link
Contributor

62mkv commented Mar 7, 2019

Just a guess - from what I've read so far, how can one be sure that @DirtiesContext actually closes the context? To me it reads as the context is thrown out of the cache, and is guaranteed to not be re-used but that does not imply (or does it?) that it's gracefully closed before next test class is being executed?

As of the H2 in-memory database, it's documentation actually says that even without explicit ;DB_CLOSE_ON_EXIT=-1 it stays alive until at least current JVM process termination, which to me, again, means that it's bound to be in place till all the test suites are executed.

So, long story short - what are the best practices to ensure pristine in-memory DB for every individual Test class in a typical Spring Boot application? (other than overriding spring.datasource.url on every integrated test class)

@62mkv
Copy link
Contributor

62mkv commented Mar 11, 2019

talking to myself here.. so, if spring-boot-devtools are on the classpath, (and they are, if you run JHipster-generated microservice in "dev" profile), there's autoconfigured bean InMemoryDatabaseShutdown, which has destroy method that issues "SHUTDOWN" command into database handle, so if you're using @DirtiesContext without overriding spring.datasource.url, then well, get ready for "fun" ... Other tests might be re-using cached context which has same datasource URL that was instantiated before @DirtiesContext test class has been executed, thus if they shared same in-memory instance, the class that executes after the "@DirtiesContext test class" is doomed.

Definitely not a bug, but still quite frustrating experience if you never gave much thought to how doSpringRunner-based tests actually work

@binakot
Copy link

binakot commented Aug 3, 2019

The same problem.

Using Spring Boot 2.1.6.RELEASE, Kotlin 1.3.41, Java 11, macos.

Running simple integration test for RestController -> Service -> CrudRepository -> H2.

Spring context doesn't close after all tests. HikariCP spams messages with active connections and keep JVM running...

@DirtiesContext helps. Thanks for advice. Waiting for some good fix.

@philwebb philwebb removed the type: documentation A documentation update label Jan 11, 2021
@philwebb philwebb modified the milestones: General Backlog, 2.5.x Jan 11, 2021
@philwebb philwebb added status: waiting-for-triage An issue we've not yet triaged theme: datasource Issues relating to data sources and removed type: bug A general bug labels Jan 11, 2021
@wilkinsona
Copy link
Member

The provided sample works with Spring Boot 2.3.x and 2.4.x. The earliest version where it works is 2.3.0.M1. I believe that's due to #16747 where each context now generated a unique name for the database. Setting spring.datasource.generate-unique-name back to false causes the problem to occur again.

With the change to generating unique database names by default, I think the current behaviour makes sense.

@wilkinsona wilkinsona removed this from the 2.5.x milestone Apr 13, 2021
@wilkinsona wilkinsona added status: superseded An issue that has been superseded by another and removed status: waiting-for-triage An issue we've not yet triaged labels Apr 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: superseded An issue that has been superseded by another theme: datasource Issues relating to data sources
Projects
None yet
Development

No branches or pull requests

8 participants