The query by can not return once invoked


(Jiachuan Li) #1

Hi Team

We are using M12 Tutorial with the serviceHub.vaultService.queryBy method to retrieve one linearState and want to use it as input state for a new transaction, but the queryBy function could not return anything back, below are the codes we are using, and with the exceptions we found from the log. Kindly help to provide some comments about this. Thanks a lot.

The iou.iou.linearId is the linearId we passed from the web UI. Could you pleas also help to confirm whether below our planned method to receive the queryBy function is correct.
val inputState: StateAndRef = serviceHub.vaultService.queryBy(linearStateCriteria).states.first()

below is the code we add in the initiator flow:
@Suspendable
override fun call(): SignedTransaction {
// Obtain a reference to the notary we want to use.
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity

        // Stage 1.
        progressTracker.currentStep = GENERATING_TRANSACTION
        // Generate an unsigned transaction.
        var txCommand : Command
        var unsignedTx : TransactionBuilder = TransactionType.General.Builder(notary)
        // If this is a new generate IOU
        if (iou.iou.status == "0") {
            txCommand = Command(IOUContract.Commands.Create(), iou.participants.map { it.owningKey })
            unsignedTx.addCommand(txCommand)
            unsignedTx.addOutputState(iou)
        }
        // If this is an existing IOU and will be approved/rejected
        if (iou.iou.status == "1" || iou.iou.status == "2") {
            //Get input state
            val uniqueIdentifier: UniqueIdentifier = UniqueIdentifier(null, UUID.fromString(iou.iou.linearId))
            val linearStateCriteria = QueryCriteria.LinearStateQueryCriteria(linearId = listOf(uniqueIdentifier))
           // val inputState: StateAndRef<LinearState> = serviceHub.vaultService.queryBy<LinearState>(linearStateCriteria).states.first()

            var output: IOUState = inputState.state.data.copy()
            output.iou.status = iou.iou.status
            txCommand = Command(IOUContract.Commands.Approve(), iou.participants.map { it.owningKey })
            unsignedTx.addInputState(inputState)
            unsignedTx.addCommand(txCommand)
            unsignedTx.addOutputState(output)
        }

Exceptions in the log as below, seems it repeatly invoke two queryBy method without an end and at last it was terminated.
[WARN ] 2017-07-06T06:35:09,399 [Node thread] flow.[3cb185f2-60dd-4924-ad0c-ab8e3c0d4f1e].run - Terminated by unexpected exception

java.lang.StackOverflowError: null
at net.corda.core.node.services.VaultService$DefaultImpls.queryBy(Services.kt:211) ~[core-0.12.1.jar:?]
at net.corda.node.services.vault.NodeVaultService.queryBy(NodeVaultService.kt:60) ~[node-0.12.1.jar:?]
at net.corda.core.node.services.VaultService$DefaultImpls.queryBy(Services.kt:211) ~[core-0.12.1.jar:?]
at net.corda.node.services.vault.NodeVaultService.queryBy(NodeVaultService.kt:60) ~[node-0.12.1.jar:?]
at net.corda.core.node.services.VaultService$DefaultImpls.queryBy(Services.kt:211) ~[core-0.12.1.jar:?]
at net.corda.node.services.vault.NodeVaultService.queryBy(NodeVaultService.kt:60) ~[node-0.12.1.jar:?]
at net.corda.core.node.services.VaultService$DefaultImpls.queryBy(Services.kt:211) ~[core-0.12.1.jar:?]
at net.corda.node.services.vault.NodeVaultService.queryBy(NodeVaultService.kt:60) ~[node-0.12.1.jar:?]
at net.corda.core.node.services.VaultService$DefaultImpls.queryBy(Services.kt:211) ~[core-0.12.1.jar:?]
at net.corda.node.services.vault.NodeVaultService.queryBy(NodeVaultService.kt:60) ~[node-0.12.1.jar:?]
at net.corda.core.node.services.VaultService$DefaultImpls.queryBy(Services.kt:211) ~[core-0.12.1.jar:?]
at net.corda.node.services.vault.NodeVaultService.queryBy(NodeVaultService.kt:60) ~[node-0.12.1.jar:?]


(Jose Coll) #2

Hi, you need to be on M13 to use the new vault query service.the APIs are not yet implemented in M12 (only the interface specification).
Apologies for any confusion.


(Jiachuan Li) #3

Hi, @josecoll

I just checked M13’s VaultQueryService.queryBy method and I saw it has a new parameter “contractType: Class<out T>”, but I didn’t find a sample code about how to initial this contractType and pass it into the function. Could you please provide one example about how should I define this first paramter for queryBy? Below is my current code: Thanks.

val linearId: UniqueIdentifier = UniqueIdentifier(null, UUID.fromString(legalContractState.legalContract.linearId))
val linearStateCriteria = QueryCriteria.LinearStateQueryCriteria(linearId = listOf(linearId))
val inputState: StateAndRef = serviceHub.vaultQueryService.queryBy(linearStateCriteria).states.single()


(Jose Coll) #4

Try the following:

val linearStateCriteria = QueryCriteria.LinearStateQueryCriteria(linearId = listOf(legalContractState.legalContract.linearId))
val inputState = services.vaultQueryService.queryBy<LinearState>(linearStateCriteria).states.single()

(Jiachuan Li) #5

hi Jose

The issue is queryBy requires two passed in parameters, but we only have one, I am not sure how should I initiate the first parameter “contractType: Class”. I attached two screenshots to make this more clear.Could you please provide a comment about how should I initiate the first position’s parameter?


(Sean Zhang) #6

Interesting - you got the interface for queryBy. Here is itsimplementation via inline extension
inline fun VaultQueryService.queryBy(criteria: QueryCriteria): Vault.Page {
return _queryBy(criteria, PageSpecification(), Sort(emptySet()), T::class.java)
}
So, the so-called contractType in your case is just LinearState::class.java
BTW, the naming of the parameter contractType seems confusing. Maybe it should be named as contractStateType.

\Sean


(Jose Coll) #7

Thanks for highlighting these two points:

  1. The java helper methods (on the interface) should indeed specify contractStateType (not contractType)
    I’ll add a clean-up task for this.
  2. The Kotlin inline extension methods annoyingly need to be imported separately (so IntelliJ automatically defaults to attempting to use the Java interface versions - with the additional contractType parameter.
    I’ll add this annoyance to the clean-up task (to see if we can improve usability)

On a 3rd note (in terms of usability annoyances), when selecting a QueryCriteria, the IDE automatically inlines the full name of the selected criteria (eg. QueryCriteria.VaultQueryCriteria() or QueryCriteria.LinearStateQueryCriteria() or QueryCriteria.FungibleAssetQueryCriteria or QueryCriteria.VaultCustomQueryCriteria) rather than importing the individual selected criteria. This leads to very lengthy and verbose criteria specifications.
Again, will add to the clean-up task (to see if we can improve usability and minimise verbosity).

Thanks for your feedback.


(Jiachuan Li) #8

Thanks Jose for this comments :slight_smile: