mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
Corda now works with H2 without the need to allow Hibernate to create the database automatically. (#2124)
[CORDA-815]: Corda now instructs Hibernate to either adjust or validate the schema based on `devMode` property. Also renamed property `database.initDatabase` to `database.createSchemaAutomatically`. * [CORDA-815]: Renamed database.initDatabase to database.adjustSchemas. * Code review changes: removed property `database.initDatabase` altogether. * Code review changes: removed property `database.initDatabase` altogether. * Code review changes: removed property `database.initDatabase` altogether. * Code review changes: removed property `database.initDatabase` altogether.
This commit is contained in:
committed by
GitHub
parent
74bf00c155
commit
cb1fa2e017
@ -65,6 +65,40 @@ class NodeStatePersistenceTests {
|
||||
val retrievedMessage = stateAndRef!!.state.data.message
|
||||
assertEquals(message, retrievedMessage)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `persistent state survives node restart without reinitialising database schema`() {
|
||||
// Temporary disable this test when executed on Windows. It is known to be sporadically failing.
|
||||
// More investigation is needed to establish why.
|
||||
assumeFalse(System.getProperty("os.name").toLowerCase().startsWith("win"))
|
||||
|
||||
val user = User("mark", "dadada", setOf(startFlow<SendMessageFlow>(), invokeRpc("vaultQuery")))
|
||||
val message = Message("Hello world!")
|
||||
val stateAndRef: StateAndRef<MessageState>? = driver(isDebug = true, startNodesInProcess = isQuasarAgentSpecified()) {
|
||||
val nodeName = {
|
||||
val nodeHandle = startNode(rpcUsers = listOf(user)).getOrThrow()
|
||||
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
|
||||
// Ensure the notary node has finished starting up, before starting a flow that needs a notary
|
||||
defaultNotaryNode.getOrThrow()
|
||||
nodeHandle.rpcClientToNode().start(user.username, user.password).use {
|
||||
it.proxy.startFlow(::SendMessageFlow, message, defaultNotaryIdentity).returnValue.getOrThrow()
|
||||
}
|
||||
nodeHandle.stop()
|
||||
nodeName
|
||||
}()
|
||||
|
||||
val nodeHandle = startNode(providedName = nodeName, rpcUsers = listOf(user), customOverrides = mapOf("devMode" to "false")).getOrThrow()
|
||||
val result = nodeHandle.rpcClientToNode().start(user.username, user.password).use {
|
||||
val page = it.proxy.vaultQuery(MessageState::class.java)
|
||||
page.states.singleOrNull()
|
||||
}
|
||||
nodeHandle.stop()
|
||||
result
|
||||
}
|
||||
assertNotNull(stateAndRef)
|
||||
val retrievedMessage = stateAndRef!!.state.data.message
|
||||
assertEquals(message, retrievedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
fun isQuasarAgentSpecified(): Boolean {
|
||||
|
@ -79,7 +79,9 @@ class CordappLoader private constructor(private val cordappJarPaths: List<Restri
|
||||
*/
|
||||
@VisibleForTesting
|
||||
fun createDefaultWithTestPackages(configuration: NodeConfiguration, testPackages: List<String>): CordappLoader {
|
||||
check(configuration.devMode) { "Package scanning can only occur in dev mode" }
|
||||
if (!configuration.devMode) {
|
||||
logger.warn("Package scanning should only occur in dev mode!")
|
||||
}
|
||||
val paths = getCordappsInDirectory(getCordappsPath(configuration.baseDirectory)) + testPackages.flatMap(this::createScanPackage)
|
||||
return cordappLoadersCache.computeIfAbsent(paths, { CordappLoader(paths) })
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ interface NodeConfiguration : NodeSSLConfiguration {
|
||||
val emailAddress: String
|
||||
val exportJMXto: String
|
||||
val dataSourceProperties: Properties
|
||||
val database: DatabaseConfig
|
||||
val rpcUsers: List<User>
|
||||
val devMode: Boolean
|
||||
val devModeOptions: DevModeOptions?
|
||||
@ -38,12 +37,13 @@ interface NodeConfiguration : NodeSSLConfiguration {
|
||||
val useTestClock: Boolean get() = false
|
||||
val detectPublicIp: Boolean get() = true
|
||||
val sshd: SSHDConfiguration?
|
||||
val database: DatabaseConfig
|
||||
}
|
||||
|
||||
data class DevModeOptions(val disableCheckpointChecker: Boolean = false)
|
||||
|
||||
data class DatabaseConfig(
|
||||
val initDatabase: Boolean = true,
|
||||
val initialiseSchema: Boolean = true,
|
||||
val serverNameTablePrefix: String = "",
|
||||
val transactionIsolationLevel: TransactionIsolationLevel = TransactionIsolationLevel.REPEATABLE_READ
|
||||
)
|
||||
@ -108,7 +108,6 @@ data class NodeConfigurationImpl(
|
||||
override val keyStorePassword: String,
|
||||
override val trustStorePassword: String,
|
||||
override val dataSourceProperties: Properties,
|
||||
override val database: DatabaseConfig = DatabaseConfig(),
|
||||
override val compatibilityZoneURL: URL? = null,
|
||||
override val rpcUsers: List<User>,
|
||||
override val verifierType: VerifierType,
|
||||
@ -130,9 +129,9 @@ data class NodeConfigurationImpl(
|
||||
override val activeMQServer: ActiveMqServerConfiguration,
|
||||
// TODO See TODO above. Rename this to nodeInfoPollingFrequency and make it of type Duration
|
||||
override val additionalNodeInfoPollingFrequencyMsec: Long = 5.seconds.toMillis(),
|
||||
override val sshd: SSHDConfiguration? = null
|
||||
|
||||
) : NodeConfiguration {
|
||||
override val sshd: SSHDConfiguration? = null,
|
||||
override val database: DatabaseConfig = DatabaseConfig(initialiseSchema = devMode)
|
||||
) : NodeConfiguration {
|
||||
override val exportJMXto: String get() = "http"
|
||||
|
||||
init {
|
||||
|
@ -54,7 +54,7 @@ class HibernateConfiguration(val schemaService: SchemaService, private val datab
|
||||
// necessarily remain and would likely be replaced by something like Liquibase. For now it is very convenient though.
|
||||
// TODO: replace auto schema generation as it isn't intended for production use, according to Hibernate docs.
|
||||
val config = Configuration(metadataSources).setProperty("hibernate.connection.provider_class", NodeDatabaseConnectionProvider::class.java.name)
|
||||
.setProperty("hibernate.hbm2ddl.auto", if (databaseConfig.initDatabase) "update" else "validate")
|
||||
.setProperty("hibernate.hbm2ddl.auto", if (databaseConfig.initialiseSchema) "update" else "validate")
|
||||
.setProperty("hibernate.format_sql", "true")
|
||||
.setProperty("hibernate.connection.isolation", databaseConfig.transactionIsolationLevel.jdbcValue.toString())
|
||||
|
||||
|
@ -90,6 +90,7 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
|
||||
var externalId: String?,
|
||||
|
||||
@Column(name = "uuid", nullable = false)
|
||||
@Type(type = "uuid-char")
|
||||
var uuid: UUID
|
||||
) : PersistentState() {
|
||||
constructor(uid: UniqueIdentifier, _participants: List<AbstractParty>) :
|
||||
|
@ -11,7 +11,6 @@ dataSourceProperties = {
|
||||
}
|
||||
database = {
|
||||
transactionIsolationLevel = "REPEATABLE_READ"
|
||||
initDatabase = true
|
||||
}
|
||||
devMode = true
|
||||
useHTTPS = false
|
||||
|
@ -38,7 +38,6 @@ class NodeConfigurationImplTest {
|
||||
keyStorePassword = "cordacadevpass",
|
||||
trustStorePassword = "trustpass",
|
||||
dataSourceProperties = makeTestDataSourceProperties(ALICE.name.organisation),
|
||||
database = DatabaseConfig(),
|
||||
rpcUsers = emptyList(),
|
||||
verifierType = VerifierType.InMemory,
|
||||
useHTTPS = false,
|
||||
|
Reference in New Issue
Block a user