Szymon db confing (#1141)

database transaction isolation level and database initialisation are configurable
This commit is contained in:
szymonsztuka 2017-07-31 16:36:34 +01:00 committed by GitHub
parent 9eb1a0c9d5
commit 7620874e5f
34 changed files with 153 additions and 85 deletions

View File

@ -15,6 +15,7 @@ import net.corda.node.utilities.configureDatabase
import net.corda.testing.*
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@ -212,7 +213,7 @@ class CommercialPaperTestsGeneric {
fun `issue move and then redeem`() {
initialiseTestSerialization()
val dataSourcePropsAlice = makeTestDataSourceProperties()
val databaseAlice = configureDatabase(dataSourcePropsAlice)
val databaseAlice = configureDatabase(dataSourcePropsAlice, makeTestDatabaseProperties())
databaseAlice.transaction {
aliceServices = object : MockServices(ALICE_KEY) {
@ -231,7 +232,7 @@ class CommercialPaperTestsGeneric {
}
val dataSourcePropsBigCorp = makeTestDataSourceProperties()
val databaseBigCorp = configureDatabase(dataSourcePropsBigCorp)
val databaseBigCorp = configureDatabase(dataSourcePropsBigCorp, makeTestDatabaseProperties())
databaseBigCorp.transaction {
bigCorpServices = object : MockServices(BIG_CORP_KEY) {

View File

@ -21,6 +21,7 @@ import net.corda.testing.contracts.fillWithSomeTestCash
import net.corda.testing.node.MockKeyManagementService
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.junit.Before
import org.junit.Test
import java.security.KeyPair
@ -51,7 +52,7 @@ class CashTests : TestDependencyInjectionBase() {
fun setUp() {
LogHelper.setLevel(NodeVaultService::class)
val dataSourceProps = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProps)
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties())
database.transaction {
miniCorpServices = object : MockServices(MINI_CORP_KEY) {
override val keyManagementService: MockKeyManagementService = MockKeyManagementService(identityService, MINI_CORP_KEY, MEGA_CORP_KEY, OUR_KEY)

View File

@ -13,6 +13,7 @@ import junit.framework.TestSuite
import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.initialiseTestSerialization
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import net.corda.testing.resetTestSerialization
import org.assertj.core.api.Assertions.assertThat
import org.jetbrains.exposed.sql.Transaction
@ -33,7 +34,7 @@ import java.util.*
JDBCHashMapTestSuite.SetConstrained::class)
class JDBCHashMapTestSuite {
companion object {
lateinit var transaction: Transaction
lateinit var transaction: DatabaseTransaction
lateinit var database: CordaPersistence
lateinit var loadOnInitFalseMap: JDBCHashMap<String, String>
lateinit var memoryConstrainedMap: JDBCHashMap<String, String>
@ -46,7 +47,7 @@ class JDBCHashMapTestSuite {
@BeforeClass
fun before() {
initialiseTestSerialization()
database = configureDatabase(makeTestDataSourceProperties())
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
setUpDatabaseTx()
loadOnInitFalseMap = JDBCHashMap<String, String>("test_map_false", loadOnInit = false)
memoryConstrainedMap = JDBCHashMap<String, String>("test_map_constrained", loadOnInit = false, maxBuckets = 1)
@ -105,7 +106,7 @@ class JDBCHashMapTestSuite {
.createTestSuite()
private fun setUpDatabaseTx() {
transaction = TransactionManager.currentOrNew(Connection.TRANSACTION_REPEATABLE_READ)
transaction = DatabaseTransactionManager.currentOrNew()
}
private fun closeDatabaseTx() {
@ -232,7 +233,7 @@ class JDBCHashMapTestSuite {
@Before
fun before() {
database = configureDatabase(makeTestDataSourceProperties())
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
}
@After

View File

@ -485,7 +485,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun makeVaultObservers() {
VaultSoftLockManager(services.vaultService, smm)
ScheduledActivityObserver(services)
HibernateObserver(services.vaultService.rawUpdates, HibernateConfiguration(services.schemaService))
HibernateObserver(services.vaultService.rawUpdates, HibernateConfiguration(services.schemaService, configuration.database ?: Properties()))
}
private fun makeInfo(): NodeInfo {
@ -544,7 +544,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
protected open fun initialiseDatabasePersistence(insideTransaction: () -> Unit) {
val props = configuration.dataSourceProperties
if (props.isNotEmpty()) {
this.database = configureDatabase(props)
this.database = configureDatabase(props, configuration.database)
// Now log the vendor string as this will also cause a connection to be tested eagerly.
database.transaction {
log.info("Connected to ${database.database.vendor} database.")
@ -764,7 +764,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun createAttachmentStorage(): NodeAttachmentService {
val attachmentsDir = (configuration.baseDirectory / "attachments").createDirectories()
return NodeAttachmentService(attachmentsDir, configuration.dataSourceProperties, services.monitoringService.metrics)
return NodeAttachmentService(attachmentsDir, configuration.dataSourceProperties, services.monitoringService.metrics, configuration.database)
}
private inner class ServiceHubInternalImpl : ServiceHubInternal, SingletonSerializeAsToken() {
@ -776,9 +776,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
override val validatedTransactions = makeTransactionStorage()
override val transactionVerifierService by lazy { makeTransactionVerifierService() }
override val networkMapCache by lazy { InMemoryNetworkMapCache(this) }
override val vaultService by lazy { NodeVaultService(this, configuration.dataSourceProperties) }
override val vaultService by lazy { NodeVaultService(this, configuration.dataSourceProperties, configuration.database) }
override val vaultQueryService by lazy {
HibernateVaultQueryImpl(HibernateConfiguration(schemaService), vaultService.updatesPublisher)
HibernateVaultQueryImpl(HibernateConfiguration(schemaService, configuration.database ?: Properties()), vaultService.updatesPublisher)
}
// Place the long term identity key in the KMS. Eventually, this is likely going to be separated again because
// the KMS is meant for derived temporary keys used in transactions, and we're not supposed to sign things with

View File

@ -25,6 +25,7 @@ interface NodeConfiguration : NodeSSLConfiguration {
val emailAddress: String
val exportJMXto: String
val dataSourceProperties: Properties
val database: Properties?
val rpcUsers: List<User>
val devMode: Boolean
val certificateSigningService: URL
@ -47,6 +48,7 @@ data class FullNodeConfiguration(
override val keyStorePassword: String,
override val trustStorePassword: String,
override val dataSourceProperties: Properties,
override val database: Properties?,
override val certificateSigningService: URL,
override val networkMapService: NetworkMapInfo?,
override val minimumPlatformVersion: Int = 1,

View File

@ -15,10 +15,11 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment
import org.hibernate.service.UnknownUnwrapTypeException
import java.sql.Connection
import java.util.*
import java.util.concurrent.ConcurrentHashMap
class HibernateConfiguration(val schemaService: SchemaService, val useDefaultLogging: Boolean = false) {
constructor(schemaService: SchemaService) : this(schemaService, false)
class HibernateConfiguration(val schemaService: SchemaService, val useDefaultLogging: Boolean = false, val databaseProperties: Properties) {
constructor(schemaService: SchemaService, databaseProperties: Properties) : this(schemaService, false, databaseProperties)
companion object {
val logger = loggerFor<HibernateConfiguration>()
@ -57,7 +58,7 @@ class HibernateConfiguration(val schemaService: SchemaService, val useDefaultLog
// 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", HibernateConfiguration.NodeDatabaseConnectionProvider::class.java.name)
.setProperty("hibernate.hbm2ddl.auto", "update")
.setProperty("hibernate.hbm2ddl.auto", if (databaseProperties.getProperty("initDatabase","true") == "true") "update" else "validate")
.setProperty("hibernate.show_sql", "$useDefaultLogging")
.setProperty("hibernate.format_sql", "$useDefaultLogging")
schemas.forEach { schema ->
@ -102,7 +103,7 @@ class HibernateConfiguration(val schemaService: SchemaService, val useDefaultLog
override fun supportsAggressiveRelease(): Boolean = true
override fun getConnection(): Connection {
return DatabaseTransactionManager.newTransaction(Connection.TRANSACTION_REPEATABLE_READ).connection
return DatabaseTransactionManager.newTransaction().connection
}
override fun <T : Any?> unwrap(unwrapType: Class<T>): T {

View File

@ -3,6 +3,7 @@ package net.corda.node.services.database
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import io.requery.Persistable
import io.requery.TransactionIsolation
import io.requery.meta.EntityModel
import io.requery.sql.KotlinEntityDataStore
import io.requery.sql.SchemaModifier
@ -13,7 +14,7 @@ import java.sql.Connection
import java.util.*
import java.util.concurrent.ConcurrentHashMap
class RequeryConfiguration(val properties: Properties, val useDefaultLogging: Boolean = false) {
class RequeryConfiguration(val properties: Properties, val useDefaultLogging: Boolean = false, val databaseProperties: Properties) {
companion object {
val logger = loggerFor<RequeryConfiguration>()
@ -40,11 +41,25 @@ class RequeryConfiguration(val properties: Properties, val useDefaultLogging: Bo
fun makeSessionFactoryForModel(model: EntityModel): KotlinEntityDataStore<Persistable> {
val configuration = KotlinConfigurationTransactionWrapper(model, dataSource, useDefaultLogging = this.useDefaultLogging)
val tables = SchemaModifier(configuration)
val mode = TableCreationMode.CREATE_NOT_EXISTS
tables.createTables(mode)
if (databaseProperties.getProperty("initDatabase","true") == "true" ) {
val mode = TableCreationMode.CREATE_NOT_EXISTS
tables.createTables(mode)
}
return KotlinEntityDataStore(configuration)
}
// TODO: remove once Requery supports QUERY WITH COMPOSITE_KEY IN
fun jdbcSession(): Connection = DatabaseTransactionManager.current().connection
}
fun parserTransactionIsolationLevel(property: String?) : TransactionIsolation =
when (property) {
"none" -> TransactionIsolation.NONE
"readUncommitted" -> TransactionIsolation.READ_UNCOMMITTED
"readCommitted" -> TransactionIsolation.READ_COMMITTED
"repeatableRead" -> TransactionIsolation.REPEATABLE_READ
"serializable" -> TransactionIsolation.SERIALIZABLE
else -> {
TransactionIsolation.REPEATABLE_READ
}
}

View File

@ -32,13 +32,13 @@ import javax.annotation.concurrent.ThreadSafe
* Stores attachments in H2 database.
*/
@ThreadSafe
class NodeAttachmentService(val storePath: Path, dataSourceProperties: Properties, metrics: MetricRegistry)
class NodeAttachmentService(val storePath: Path, dataSourceProperties: Properties, metrics: MetricRegistry, databaseProperties: Properties?)
: AttachmentStorage, AcceptsFileUpload, SingletonSerializeAsToken() {
companion object {
private val log = loggerFor<NodeAttachmentService>()
}
val configuration = RequeryConfiguration(dataSourceProperties)
val configuration = RequeryConfiguration(dataSourceProperties, databaseProperties = databaseProperties ?: Properties())
val session = configuration.sessionForModel(Models.PERSISTENCE)
@VisibleForTesting

View File

@ -57,7 +57,7 @@ class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
DatabaseTransactionManager.current().close()
Strand.sleep(millis)
DatabaseTransactionManager.dataSource = db
DatabaseTransactionManager.newTransaction(Connection.TRANSACTION_REPEATABLE_READ)
DatabaseTransactionManager.newTransaction()
} else Strand.sleep(millis)
}
}

View File

@ -34,6 +34,7 @@ import net.corda.core.serialization.serialize
import net.corda.core.transactions.*
import net.corda.core.utilities.*
import net.corda.node.services.database.RequeryConfiguration
import net.corda.node.services.database.parserTransactionIsolationLevel
import net.corda.node.services.statemachine.FlowStateMachineImpl
import net.corda.node.services.vault.schemas.requery.Models
import net.corda.node.services.vault.schemas.requery.VaultSchema
@ -60,7 +61,7 @@ import kotlin.concurrent.withLock
* TODO: keep an audit trail with time stamps of previously unconsumed states "as of" a particular point in time.
* TODO: have transaction storage do some caching.
*/
class NodeVaultService(private val services: ServiceHub, dataSourceProperties: Properties) : SingletonSerializeAsToken(), VaultService {
class NodeVaultService(private val services: ServiceHub, dataSourceProperties: Properties, databaseProperties: Properties?) : SingletonSerializeAsToken(), VaultService {
private companion object {
val log = loggerFor<NodeVaultService>()
@ -69,8 +70,9 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
val stateRefCompositeColumn: RowExpression = RowExpression.of(listOf(VaultStatesEntity.TX_ID, VaultStatesEntity.INDEX))
}
val configuration = RequeryConfiguration(dataSourceProperties)
val configuration = RequeryConfiguration(dataSourceProperties, databaseProperties = databaseProperties ?: Properties())
val session = configuration.sessionForModel(Models.VAULT)
private val transactionIsolationLevel = parserTransactionIsolationLevel(databaseProperties?.getProperty("transactionIsolationLevel") ?:"")
private class InnerState {
val _updatesPublisher = PublishSubject.create<Vault.Update<ContractState>>()!!
@ -89,7 +91,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
val consumedStateRefs = update.consumed.map { it.ref }
log.trace { "Removing $consumedStateRefs consumed contract states and adding $producedStateRefs produced contract states to the database." }
session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
session.withTransaction(transactionIsolationLevel) {
producedStateRefsMap.forEach { it ->
val state = VaultStatesEntity().apply {
txId = it.key.txhash.toString()
@ -142,7 +144,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
override fun <T : ContractState> states(clazzes: Set<Class<T>>, statuses: EnumSet<Vault.StateStatus>, includeSoftLockedStates: Boolean): Iterable<StateAndRef<T>> {
val stateAndRefs =
session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
session.withTransaction(transactionIsolationLevel) {
val query = select(VaultSchema.VaultStates::class)
.where(VaultSchema.VaultStates::stateStatus `in` statuses)
// TODO: temporary fix to continue supporting track() function (until becomes Typed)
@ -164,7 +166,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
override fun statesForRefs(refs: List<StateRef>): Map<StateRef, TransactionState<*>?> {
val stateAndRefs =
session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
session.withTransaction(transactionIsolationLevel) {
var results: List<StateAndRef<*>> = emptyList()
refs.forEach {
val result = select(VaultSchema.VaultStates::class)
@ -273,7 +275,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
private fun loadStates(refs: Collection<StateRef>): HashSet<StateAndRef<ContractState>> {
val states = HashSet<StateAndRef<ContractState>>()
if (refs.isNotEmpty()) {
session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
session.withTransaction(transactionIsolationLevel) {
val result = select(VaultStatesEntity::class).
where(stateRefCompositeColumn.`in`(stateRefArgs(refs))).
and(VaultSchema.VaultStates::stateStatus eq Vault.StateStatus.UNCONSUMED)
@ -301,7 +303,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
}
override fun addNoteToTransaction(txnId: SecureHash, noteText: String) {
session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
session.withTransaction(transactionIsolationLevel) {
val txnNoteEntity = VaultTxnNoteEntity()
txnNoteEntity.txId = txnId.toString()
txnNoteEntity.note = noteText
@ -310,7 +312,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
}
override fun getTransactionNotes(txnId: SecureHash): Iterable<String> {
return session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
return session.withTransaction(transactionIsolationLevel) {
(select(VaultSchema.VaultTxnNote::class) where (VaultSchema.VaultTxnNote::txId eq txnId.toString())).get().asIterable().map { it.note }
}
}
@ -320,7 +322,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
val softLockTimestamp = services.clock.instant()
val stateRefArgs = stateRefArgs(stateRefs)
try {
session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
session.withTransaction(transactionIsolationLevel) {
val updatedRows = update(VaultStatesEntity::class)
.set(VaultStatesEntity.LOCK_ID, lockId.toString())
.set(VaultStatesEntity.LOCK_UPDATE_TIME, softLockTimestamp)
@ -353,7 +355,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
override fun softLockRelease(lockId: UUID, stateRefs: NonEmptySet<StateRef>?) {
if (stateRefs == null) {
session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
session.withTransaction(transactionIsolationLevel) {
val update = update(VaultStatesEntity::class)
.set(VaultStatesEntity.LOCK_ID, null)
.set(VaultStatesEntity.LOCK_UPDATE_TIME, services.clock.instant())
@ -365,7 +367,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
}
} else {
try {
session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
session.withTransaction(transactionIsolationLevel) {
val updatedRows = update(VaultStatesEntity::class)
.set(VaultStatesEntity.LOCK_ID, null)
.set(VaultStatesEntity.LOCK_UPDATE_TIME, services.clock.instant())
@ -482,7 +484,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
override fun <T : ContractState> softLockedStates(lockId: UUID?): List<StateAndRef<T>> {
val stateAndRefs =
session.withTransaction(TransactionIsolation.REPEATABLE_READ) {
session.withTransaction(transactionIsolationLevel) {
val query = select(VaultSchema.VaultStates::class)
.where(VaultSchema.VaultStates::stateStatus eq Vault.StateStatus.UNCONSUMED)
.and(VaultSchema.VaultStates::contractStateClassName eq Cash.State::class.java.name)

View File

@ -14,15 +14,16 @@ import java.util.*
import java.util.concurrent.CopyOnWriteArrayList
//HikariDataSource implements also Closeable which allows CordaPersistence to be Closeable
class CordaPersistence(var dataSource: HikariDataSource): Closeable {
//HikariDataSource implements Closeable which allows CordaPersistence to be Closeable
class CordaPersistence(var dataSource: HikariDataSource, databaseProperties: Properties): Closeable {
/** Holds Exposed database, the field will be removed once Exposed library is removed */
lateinit var database: Database
var transactionIsolationLevel = parserTransactionIsolationLevel(databaseProperties.getProperty("transactionIsolationLevel"))
companion object {
fun connect(dataSource: HikariDataSource): CordaPersistence {
return CordaPersistence(dataSource).apply {
fun connect(dataSource: HikariDataSource, databaseProperties: Properties): CordaPersistence {
return CordaPersistence(dataSource, databaseProperties).apply {
DatabaseTransactionManager(this)
}
}
@ -31,7 +32,7 @@ class CordaPersistence(var dataSource: HikariDataSource): Closeable {
fun createTransaction(): DatabaseTransaction {
// We need to set the database for the current [Thread] or [Fiber] here as some tests share threads across databases.
DatabaseTransactionManager.dataSource = this
return DatabaseTransactionManager.currentOrNew(Connection.TRANSACTION_REPEATABLE_READ)
return DatabaseTransactionManager.currentOrNew(transactionIsolationLevel)
}
fun <T> isolatedTransaction(block: DatabaseTransaction.() -> T): T {
@ -45,7 +46,7 @@ class CordaPersistence(var dataSource: HikariDataSource): Closeable {
fun <T> transaction(statement: DatabaseTransaction.() -> T): T {
DatabaseTransactionManager.dataSource = this
return transaction(Connection.TRANSACTION_REPEATABLE_READ, 3, statement)
return transaction(transactionIsolationLevel, 3, statement)
}
private fun <T> transaction(transactionIsolation: Int, repetitionAttempts: Int, statement: DatabaseTransaction.() -> T): T {
@ -90,10 +91,10 @@ class CordaPersistence(var dataSource: HikariDataSource): Closeable {
}
}
fun configureDatabase(props: Properties): CordaPersistence {
val config = HikariConfig(props)
fun configureDatabase(dataSourceProperties: Properties, databaseProperties: Properties?): CordaPersistence {
val config = HikariConfig(dataSourceProperties)
val dataSource = HikariDataSource(config)
val persistence = CordaPersistence.connect(dataSource)
val persistence = CordaPersistence.connect(dataSource, databaseProperties ?: Properties())
//org.jetbrains.exposed.sql.Database will be removed once Exposed library is removed
val database = Database.connect(dataSource) { _ -> ExposedTransactionManager() }
@ -191,3 +192,16 @@ fun <T : Any> rx.Observable<T>.wrapWithDatabaseTransaction(db: CordaPersistence?
}
}
}
fun parserTransactionIsolationLevel(property: String?) : Int =
when (property) {
"none" -> Connection.TRANSACTION_NONE
"readUncommitted" -> Connection.TRANSACTION_READ_UNCOMMITTED
"readCommitted" -> Connection.TRANSACTION_READ_COMMITTED
"repeatableRead" -> Connection.TRANSACTION_REPEATABLE_READ
"serializable" -> Connection.TRANSACTION_SERIALIZABLE
else -> {
Connection.TRANSACTION_REPEATABLE_READ
}
}

View File

@ -74,11 +74,11 @@ class DatabaseTransactionManager(initDataSource: CordaPersistence) {
fun currentOrNull(): DatabaseTransaction? = manager.currentOrNull()
fun currentOrNew(isolation: Int) = currentOrNull() ?: manager.newTransaction(isolation)
fun currentOrNew(isolation: Int = dataSource.transactionIsolationLevel) = currentOrNull() ?: manager.newTransaction(isolation)
fun current(): DatabaseTransaction = currentOrNull() ?: error("No transaction in context.")
fun newTransaction(isolation: Int) = manager.newTransaction(isolation)
fun newTransaction(isolation: Int = dataSource.transactionIsolationLevel) = manager.newTransaction(isolation)
}
data class Boundary(val txId: UUID)

View File

@ -9,6 +9,10 @@ dataSourceProperties = {
"dataSource.user" = sa
"dataSource.password" = ""
}
database = {
transactionIsolationLevel = "repeatableRead"
initDatabase = true
}
devMode = true
certificateSigningService = "https://cordaci-netperm.corda.r3cev.com"
useHTTPS = false

View File

@ -52,6 +52,7 @@ import static net.corda.core.utilities.ByteArrays.toHexString;
import static net.corda.node.utilities.CordaPersistenceKt.configureDatabase;
import static net.corda.testing.CoreTestUtils.*;
import static net.corda.testing.node.MockServicesKt.makeTestDataSourceProperties;
import static net.corda.testing.node.MockServicesKt.makeTestDatabaseProperties;
import static org.assertj.core.api.Assertions.assertThat;
public class VaultQueryJavaTests extends TestDependencyInjectionBase {
@ -64,10 +65,10 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
@Before
public void setUp() {
Properties dataSourceProps = makeTestDataSourceProperties(SecureHash.randomSHA256().toString());
database = configureDatabase(dataSourceProps);
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties());
Set<MappedSchema> customSchemas = new HashSet<>(Collections.singletonList(DummyLinearStateSchemaV1.INSTANCE));
HibernateConfiguration hibernateConfig = new HibernateConfiguration(new NodeSchemaService(customSchemas));
HibernateConfiguration hibernateConfig = new HibernateConfiguration(new NodeSchemaService(customSchemas), makeTestDatabaseProperties());
database.transaction(
statement -> { services = new MockServices(getMEGA_CORP_KEY()) {
@NotNull

View File

@ -15,6 +15,7 @@ import net.corda.node.services.persistence.schemas.requery.AttachmentEntity
import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.junit.After
import org.junit.Before
import org.junit.Test
@ -35,7 +36,7 @@ class AttachmentTests {
fun setUp() {
mockNet = MockNetwork()
val dataSourceProperties = makeTestDataSourceProperties()
configuration = RequeryConfiguration(dataSourceProperties)
configuration = RequeryConfiguration(dataSourceProperties, databaseProperties = makeTestDatabaseProperties())
}
@After

View File

@ -5,6 +5,7 @@ import net.corda.core.utilities.NetworkHostAndPort
import net.corda.testing.ALICE
import net.corda.nodeapi.User
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Test
import java.net.URL
@ -21,6 +22,7 @@ class FullNodeConfigurationTest {
keyStorePassword = "cordacadevpass",
trustStorePassword = "trustpass",
dataSourceProperties = makeTestDataSourceProperties(ALICE.name.commonName),
database = makeTestDatabaseProperties(),
certificateSigningService = URL("http://localhost"),
rpcUsers = emptyList(),
verifierType = VerifierType.InMemory,

View File

@ -27,6 +27,7 @@ import net.corda.testing.contracts.fillWithSomeTestDeals
import net.corda.testing.contracts.fillWithSomeTestLinearStates
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import net.corda.testing.schemas.DummyLinearStateSchemaV1
import net.corda.testing.schemas.DummyLinearStateSchemaV2
import org.assertj.core.api.Assertions
@ -60,16 +61,17 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
@Before
fun setUp() {
val dataSourceProps = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProps)
val defaultDatabaseProperties = makeTestDatabaseProperties()
database = configureDatabase(dataSourceProps, defaultDatabaseProperties)
val customSchemas = setOf(VaultSchemaV1, CashSchemaV1, SampleCashSchemaV2, SampleCashSchemaV3)
database.transaction {
hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas))
hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties())
services = object : MockServices(BOB_KEY) {
override val vaultService: VaultService get() {
val vaultService = NodeVaultService(this, dataSourceProps)
val vaultService = NodeVaultService(this, dataSourceProps, makeTestDatabaseProperties())
hibernatePersister = HibernateObserver(vaultService.rawUpdates, hibernateConfig)
return vaultService
}

View File

@ -25,6 +25,7 @@ import net.corda.testing.DUMMY_PUBKEY_1
import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.contracts.DummyContract
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.assertj.core.api.Assertions
import org.junit.After
import org.junit.Assert.assertEquals
@ -43,7 +44,7 @@ class RequeryConfigurationTest : TestDependencyInjectionBase() {
@Before
fun setUp() {
val dataSourceProperties = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProperties)
database = configureDatabase(dataSourceProperties, makeTestDatabaseProperties())
newTransactionStorage()
newRequeryStorage(dataSourceProperties)
}
@ -157,7 +158,7 @@ class RequeryConfigurationTest : TestDependencyInjectionBase() {
val nativeQuery = "SELECT v.transaction_id, v.output_index FROM vault_states v WHERE v.state_status = 0"
database.transaction {
val configuration = RequeryConfiguration(dataSourceProperties, true)
val configuration = RequeryConfiguration(dataSourceProperties, true, makeTestDatabaseProperties())
val jdbcSession = configuration.jdbcSession()
val prepStatement = jdbcSession.prepareStatement(nativeQuery)
val rs = prepStatement.executeQuery()
@ -197,7 +198,7 @@ class RequeryConfigurationTest : TestDependencyInjectionBase() {
private fun newRequeryStorage(dataSourceProperties: Properties) {
database.transaction {
val configuration = RequeryConfiguration(dataSourceProperties, true)
val configuration = RequeryConfiguration(dataSourceProperties, true, makeTestDatabaseProperties())
requerySession = configuration.sessionForModel(Models.VAULT)
}
}

View File

@ -21,12 +21,10 @@ import net.corda.node.services.statemachine.StateMachineManager
import net.corda.node.services.vault.NodeVaultService
import net.corda.node.utilities.*
import net.corda.testing.getTestX509Name
import net.corda.testing.node.InMemoryMessagingNetwork
import net.corda.testing.node.MockKeyManagementService
import net.corda.testing.node.TestClock
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.testNodeConfiguration
import net.corda.testing.initialiseTestSerialization
import net.corda.testing.node.*
import net.corda.testing.node.TestClock
import net.corda.testing.resetTestSerialization
import org.assertj.core.api.Assertions.assertThat
import org.bouncycastle.asn1.x500.X500Name
@ -37,6 +35,7 @@ import java.nio.file.Paths
import java.security.PublicKey
import java.time.Clock
import java.time.Instant
import java.util.*
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
@ -75,7 +74,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
smmHasRemovedAllFlows = CountDownLatch(1)
calls = 0
val dataSourceProps = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProps)
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties())
val identityService = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
val kms = MockKeyManagementService(identityService, ALICE_KEY)
@ -92,7 +91,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
overrideClock = testClock,
keyManagement = kms,
network = mockMessagingService), TestReference {
override val vaultService: VaultService = NodeVaultService(this, dataSourceProps)
override val vaultService: VaultService = NodeVaultService(this, dataSourceProps, makeTestDatabaseProperties())
override val testReference = this@NodeSchedulerServiceTest
}
scheduler = NodeSchedulerService(services, schedulerGatedExecutor)

View File

@ -22,6 +22,7 @@ import net.corda.node.utilities.configureDatabase
import net.corda.testing.*
import net.corda.testing.node.MOCK_VERSION_INFO
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.After
@ -30,6 +31,7 @@ import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import java.net.ServerSocket
import java.util.*
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.TimeUnit.MILLISECONDS
import kotlin.concurrent.thread
@ -68,7 +70,7 @@ class ArtemisMessagingTests : TestDependencyInjectionBase() {
baseDirectory = baseDirectory,
myLegalName = ALICE.name)
LogHelper.setLevel(PersistentUniquenessProvider::class)
database = configureDatabase(makeTestDataSourceProperties())
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
networkMapRegistrationFuture = Futures.immediateFuture(Unit)
}

View File

@ -10,6 +10,7 @@ import net.corda.node.utilities.configureDatabase
import net.corda.testing.LogHelper
import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.junit.After
@ -32,7 +33,7 @@ class DBCheckpointStorageTests : TestDependencyInjectionBase() {
@Before
fun setUp() {
LogHelper.setLevel(PersistentUniquenessProvider::class)
database = configureDatabase(makeTestDataSourceProperties())
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
newCheckpointStorage()
}

View File

@ -14,6 +14,7 @@ import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.LogHelper
import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
@ -28,7 +29,7 @@ class DBTransactionStorageTests : TestDependencyInjectionBase() {
@Before
fun setUp() {
LogHelper.setLevel(PersistentUniquenessProvider::class)
database = configureDatabase(makeTestDataSourceProperties())
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
newTransactionStorage()
}

View File

@ -16,6 +16,7 @@ import net.corda.node.services.transactions.PersistentUniquenessProvider
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.junit.After
import org.junit.Before
import org.junit.Test
@ -42,9 +43,9 @@ class NodeAttachmentStorageTest {
LogHelper.setLevel(PersistentUniquenessProvider::class)
dataSourceProperties = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProperties)
database = configureDatabase(dataSourceProperties, makeTestDatabaseProperties())
configuration = RequeryConfiguration(dataSourceProperties)
configuration = RequeryConfiguration(dataSourceProperties, databaseProperties = makeTestDatabaseProperties())
fs = Jimfs.newFileSystem(Configuration.unix())
}
@ -59,7 +60,7 @@ class NodeAttachmentStorageTest {
val expectedHash = testJar.readAll().sha256()
database.transaction {
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry())
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties())
val id = testJar.read { storage.importAttachment(it) }
assertEquals(expectedHash, id)
@ -85,7 +86,7 @@ class NodeAttachmentStorageTest {
fun `duplicates not allowed`() {
val testJar = makeTestJar()
database.transaction {
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry())
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties())
testJar.read {
storage.importAttachment(it)
}
@ -101,7 +102,7 @@ class NodeAttachmentStorageTest {
fun `corrupt entry throws exception`() {
val testJar = makeTestJar()
database.transaction {
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry())
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties())
val id = testJar.read { storage.importAttachment(it) }
// Corrupt the file in the store.
@ -129,7 +130,7 @@ class NodeAttachmentStorageTest {
@Test
fun `non jar rejected`() {
database.transaction {
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry())
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry(), makeTestDatabaseProperties())
val path = fs.getPath("notajar")
path.writeLines(listOf("Hey", "there!"))
path.read {

View File

@ -14,6 +14,7 @@ import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase
import net.corda.testing.MEGA_CORP
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.hibernate.annotations.Cascade
import org.hibernate.annotations.CascadeType
import org.jetbrains.exposed.sql.transactions.TransactionManager
@ -31,7 +32,7 @@ class HibernateObserverTests {
@Before
fun setUp() {
LogHelper.setLevel(HibernateObserver::class)
database = configureDatabase(makeTestDataSourceProperties())
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
}
@After
@ -101,7 +102,7 @@ class HibernateObserverTests {
}
@Suppress("UNUSED_VARIABLE")
val observer = HibernateObserver(rawUpdatesPublisher, HibernateConfiguration(schemaService))
val observer = HibernateObserver(rawUpdatesPublisher, HibernateConfiguration(schemaService, makeTestDatabaseProperties()))
database.transaction {
rawUpdatesPublisher.onNext(Vault.Update(emptySet(), setOf(StateAndRef(TransactionState(TestState(), MEGA_CORP), StateRef(SecureHash.sha256("dummy"), 0)))))
val parentRowCountResult = TransactionManager.current().connection.prepareStatement("select count(*) from Parents").executeQuery()

View File

@ -15,6 +15,7 @@ import net.corda.testing.LogHelper
import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.freeLocalHostAndPort
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.jetbrains.exposed.sql.Transaction
import org.junit.After
import org.junit.Before
@ -34,7 +35,7 @@ class DistributedImmutableMapTests : TestDependencyInjectionBase() {
fun setup() {
LogHelper.setLevel("-org.apache.activemq")
LogHelper.setLevel(NetworkMapService::class)
database = configureDatabase(makeTestDataSourceProperties())
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
cluster = setUpCluster()
}

View File

@ -9,6 +9,7 @@ import net.corda.testing.MEGA_CORP
import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.generateStateRef
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.junit.After
import org.junit.Before
import org.junit.Test
@ -24,7 +25,7 @@ class PersistentUniquenessProviderTests : TestDependencyInjectionBase() {
@Before
fun setUp() {
LogHelper.setLevel(PersistentUniquenessProvider::class)
database = configureDatabase(makeTestDataSourceProperties())
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
}
@After

View File

@ -23,6 +23,7 @@ import net.corda.testing.*
import net.corda.testing.contracts.fillWithSomeTestCash
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import net.corda.testing.schemas.DummyLinearStateSchemaV1
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatExceptionOfType
@ -46,10 +47,10 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun setUp() {
LogHelper.setLevel(NodeVaultService::class)
val dataSourceProps = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProps)
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties())
database.transaction {
val customSchemas = setOf(CommercialPaperSchemaV1, DummyLinearStateSchemaV1)
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas))
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties())
services = object : MockServices() {
override val vaultService: VaultService = makeVaultService(dataSourceProps, hibernateConfig)

View File

@ -30,6 +30,7 @@ import net.corda.testing.*
import net.corda.testing.contracts.*
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import net.corda.testing.schemas.DummyLinearStateSchemaV1
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat
@ -56,10 +57,10 @@ class VaultQueryTests : TestDependencyInjectionBase() {
@Before
fun setUp() {
val dataSourceProps = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProps)
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties())
database.transaction {
val customSchemas = setOf(CommercialPaperSchemaV1, DummyLinearStateSchemaV1)
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas))
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties())
services = object : MockServices(MEGA_CORP_KEY) {
override val vaultService: VaultService = makeVaultService(dataSourceProps, hibernateConfig)
@ -86,7 +87,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
@Ignore
@Test
fun createPersistentTestDb() {
val database = configureDatabase(makePersistentDataSourceProperties())
val database = configureDatabase(makePersistentDataSourceProperties(), makeTestDatabaseProperties())
setUpDb(database, 5000)

View File

@ -20,6 +20,7 @@ import net.corda.testing.*
import net.corda.testing.contracts.*
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import net.corda.testing.schemas.DummyLinearStateSchemaV1
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
@ -43,10 +44,10 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
fun setUp() {
LogHelper.setLevel(VaultWithCashTest::class)
val dataSourceProps = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProps)
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties())
database.transaction {
val customSchemas = setOf(CommercialPaperSchemaV1, DummyLinearStateSchemaV1)
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas))
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties())
services = object : MockServices() {
override val vaultService: VaultService = makeVaultService(dataSourceProps, hibernateConfig)

View File

@ -4,6 +4,7 @@ import com.google.common.util.concurrent.SettableFuture
import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.internal.tee
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Test
@ -19,7 +20,7 @@ class ObservablesTests {
val toBeClosed = mutableListOf<Closeable>()
fun createDatabase(): CordaPersistence {
val database = configureDatabase(makeTestDataSourceProperties())
val database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
toBeClosed += database
return database
}

View File

@ -21,6 +21,7 @@ import net.corda.testing.*
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.bouncycastle.asn1.x500.X500Name
import org.junit.After
import org.junit.Assert
@ -59,7 +60,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
@Before
fun setUp() {
database = configureDatabase(makeTestDataSourceProperties())
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties())
database.transaction {
oracle = NodeInterestRates.Oracle(
MEGA_CORP,

View File

@ -21,6 +21,7 @@ import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.nodeapi.config.SSLConfiguration
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.X500NameBuilder
import org.bouncycastle.asn1.x500.style.BCStyle
@ -163,6 +164,7 @@ fun testNodeConfiguration(
whenever(nc.trustStorePassword).thenReturn("trustpass")
whenever(nc.rpcUsers).thenReturn(emptyList())
whenever(nc.dataSourceProperties).thenReturn(makeTestDataSourceProperties(myLegalName.commonName))
whenever(nc.database).thenReturn(makeTestDatabaseProperties())
whenever(nc.emailAddress).thenReturn("")
whenever(nc.exportJMXto).thenReturn("")
whenever(nc.devMode).thenReturn(true)

View File

@ -80,8 +80,8 @@ open class MockServices(vararg val keys: KeyPair) : ServiceHub {
}
override val transactionVerifierService: TransactionVerifierService get() = InMemoryTransactionVerifierService(2)
fun makeVaultService(dataSourceProps: Properties, hibernateConfig: HibernateConfiguration = HibernateConfiguration(NodeSchemaService())): VaultService {
val vaultService = NodeVaultService(this, dataSourceProps)
fun makeVaultService(dataSourceProps: Properties, hibernateConfig: HibernateConfiguration = HibernateConfiguration(NodeSchemaService(), makeTestDatabaseProperties())): VaultService {
val vaultService = NodeVaultService(this, dataSourceProps, makeTestDatabaseProperties())
HibernateObserver(vaultService.rawUpdates, hibernateConfig)
return vaultService
}
@ -196,4 +196,10 @@ fun makeTestDataSourceProperties(nodeName: String = SecureHash.randomSHA256().to
return props
}
fun makeTestDatabaseProperties(): Properties {
val props = Properties()
props.setProperty("transactionIsolationLevel", "repeatableRead") //for other possible values see net.corda.node.utilities.CordaPeristence.parserTransactionIsolationLevel(String)
return props
}
val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor")

View File

@ -32,7 +32,7 @@ class SimpleNode(val config: NodeConfiguration, val address: NetworkHostAndPort
rpcAddress: NetworkHostAndPort = freeLocalHostAndPort(),
trustRoot: X509Certificate) : AutoCloseable {
val database: CordaPersistence = configureDatabase(config.dataSourceProperties)
val database: CordaPersistence = configureDatabase(config.dataSourceProperties, config.database)
val userService = RPCUserServiceImpl(config.rpcUsers)
val monitoringService = MonitoringService(MetricRegistry())
val identity: KeyPair = generateKeyPair()