Automatically persist Linear and/or FungibleState attributes for quer… (#920)

* Automatically persist Linear and/or FungibleState attributes for querying (even when Contract does not implement QueryableState).

* Return single() state.
This commit is contained in:
josecoll 2017-06-26 18:01:07 +01:00 committed by Konstantinos Chalkias
parent f827db72da
commit 526007a085
2 changed files with 17 additions and 16 deletions

View File

@ -2,11 +2,14 @@ package net.corda.docs
import net.corda.core.contracts.LinearState import net.corda.core.contracts.LinearState
import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.getOrThrow import net.corda.core.getOrThrow
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.linearHeadsOfType import net.corda.core.node.services.Vault
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.node.services.vault.and
import net.corda.core.toFuture import net.corda.core.toFuture
import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY
import net.corda.core.utilities.DUMMY_NOTARY_KEY import net.corda.core.utilities.DUMMY_NOTARY_KEY
@ -26,10 +29,10 @@ class WorkflowTransactionBuildTutorialTest {
lateinit var nodeB: MockNetwork.MockNode lateinit var nodeB: MockNetwork.MockNode
// Helper method to locate the latest Vault version of a LinearState from a possibly out of date StateRef // Helper method to locate the latest Vault version of a LinearState from a possibly out of date StateRef
private inline fun <reified T : LinearState> ServiceHub.latest(ref: StateRef): StateAndRef<T> { private inline fun <reified T : LinearState> ServiceHub.latest(ref: UniqueIdentifier): StateAndRef<T> {
val linearHeads = vaultService.linearHeadsOfType<T>() val linearHeads = vaultQueryService.queryBy<T>(QueryCriteria.LinearStateQueryCriteria(linearId = listOf(ref))
val original = storageService.validatedTransactions.getTransaction(ref.txhash)!!.tx.outRef<T>(ref.index) .and(QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.UNCONSUMED)))
return linearHeads[original.state.data.linearId]!! return linearHeads.states.single()
} }
@Before @Before
@ -59,14 +62,15 @@ class WorkflowTransactionBuildTutorialTest {
val flow1 = nodeA.services.startFlow(SubmitTradeApprovalFlow("1234", nodeB.info.legalIdentity)) val flow1 = nodeA.services.startFlow(SubmitTradeApprovalFlow("1234", nodeB.info.legalIdentity))
// Wait for the flow to finish // Wait for the flow to finish
val proposalRef = flow1.resultFuture.getOrThrow() val proposalRef = flow1.resultFuture.getOrThrow()
val proposalLinearId = proposalRef.state.data.linearId
// Wait for NodeB to include it's copy in the vault // Wait for NodeB to include it's copy in the vault
nodeBVaultUpdate.get() nodeBVaultUpdate.get()
// Fetch the latest copy of the state from both nodes // Fetch the latest copy of the state from both nodes
val latestFromA = nodeA.database.transaction { val latestFromA = nodeA.database.transaction {
nodeA.services.latest<TradeApprovalContract.State>(proposalRef.ref) nodeA.services.latest<TradeApprovalContract.State>(proposalLinearId)
} }
val latestFromB = nodeB.database.transaction { val latestFromB = nodeB.database.transaction {
nodeB.services.latest<TradeApprovalContract.State>(proposalRef.ref) nodeB.services.latest<TradeApprovalContract.State>(proposalLinearId)
} }
// Confirm the state as as expected // Confirm the state as as expected
assertEquals(WorkflowState.NEW, proposalRef.state.data.state) assertEquals(WorkflowState.NEW, proposalRef.state.data.state)
@ -87,10 +91,10 @@ class WorkflowTransactionBuildTutorialTest {
secondNodeBVaultUpdate.get() secondNodeBVaultUpdate.get()
// Fetch the latest copies from the vault // Fetch the latest copies from the vault
val finalFromA = nodeA.database.transaction { val finalFromA = nodeA.database.transaction {
nodeA.services.latest<TradeApprovalContract.State>(proposalRef.ref) nodeA.services.latest<TradeApprovalContract.State>(proposalLinearId)
} }
val finalFromB = nodeB.database.transaction { val finalFromB = nodeB.database.transaction {
nodeB.services.latest<TradeApprovalContract.State>(proposalRef.ref) nodeB.services.latest<TradeApprovalContract.State>(proposalLinearId)
} }
// Confirm the state is as expected // Confirm the state is as expected
assertEquals(WorkflowState.APPROVED, completedRef.state.data.state) assertEquals(WorkflowState.APPROVED, completedRef.state.data.state)

View File

@ -6,7 +6,6 @@ import net.corda.core.contracts.StateRef
import net.corda.core.node.services.Vault import net.corda.core.node.services.Vault
import net.corda.core.schemas.MappedSchema import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.PersistentStateRef import net.corda.core.schemas.PersistentStateRef
import net.corda.core.schemas.QueryableState
import net.corda.core.utilities.debug import net.corda.core.utilities.debug
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.node.services.database.HibernateConfiguration import net.corda.node.services.database.HibernateConfiguration
@ -34,13 +33,11 @@ class HibernateObserver(vaultUpdates: Observable<Vault.Update>, val config: Hibe
private fun persistState(stateAndRef: StateAndRef<ContractState>) { private fun persistState(stateAndRef: StateAndRef<ContractState>) {
val state = stateAndRef.state.data val state = stateAndRef.state.data
if (state is QueryableState) { logger.debug { "Asked to persist state ${stateAndRef.ref}" }
logger.debug { "Asked to persist state ${stateAndRef.ref}" } config.schemaService.selectSchemas(state).forEach { persistStateWithSchema(state, stateAndRef.ref, it) }
config.schemaService.selectSchemas(state).forEach { persistStateWithSchema(state, stateAndRef.ref, it) }
}
} }
fun persistStateWithSchema(state: QueryableState, stateRef: StateRef, schema: MappedSchema) { fun persistStateWithSchema(state: ContractState, stateRef: StateRef, schema: MappedSchema) {
val sessionFactory = config.sessionFactoryForSchema(schema) val sessionFactory = config.sessionFactoryForSchema(schema)
val session = sessionFactory.withOptions(). val session = sessionFactory.withOptions().
connection(TransactionManager.current().connection). connection(TransactionManager.current().connection).