Skip to content

Corda: How to use the AndComposition with a VaultCustomQueryCriteria

I use a RPC client (Java Spring Boot application) to connect to a Corda 4.6 node.

I want to run a custom vault query with the following query criteria:

QueryCriteria stateStatusCriteria = new VaultQueryCriteria(StateStatus.ALL);
QueryCriteria myFieldCriteria = new VaultCustomQueryCriteria(
  Builder.equal(getField("myField", PersistentMyState.class), myValue)
);
return stateStatusCriteria.and(myFieldCriteria);
// Also tried: return myFieldCriteria.and(stateStatusCriteria);

This is very similar to the example from the Corda documentation.

However, I just retrieve UNCONSUMED states. What could go wrong here?

The following snippet is working, but I need an AndComposition since I want to add more custom criteria later:

QueryCriteria myFieldCriteria = new VaultCustomQueryCriteria(
  Builder.equal(getField("myField", PersistentMyState.class), myValue), 
  StateStatus.ALL
);
return myFieldCriteria ;

Moreover, any hints how to activate Hibernate logging in Corda are appreciated. I am using custom CorDapps in a corda/corda-zulu-java1.8-4.6:RELEASE image running in a Kubernetes cluster with a PostgreSQL database.

Answer

** UPDATE **

The VaultCustomQueryCriteria by default set the stateStatus = UNCONSUMED in its constructor:

    data class VaultCustomQueryCriteria<L : StatePersistable>(
        val expression: CriteriaExpression<L, Boolean>,
        override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
        override val contractStateTypes: Set<Class<out ContractState>>? = null,
        override val relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL)

So, if you do not pass the StateStatus, the query will always return the UNCONSUMED states and the and() predicative of Hibernate will not work, in case you have also CONSUMED states. There is also this interesting issue on github with a similar case. So basically your first snippet should be like this:

QueryCriteria stateStatusCriteria = new VaultQueryCriteria(StateStatus.ALL);
QueryCriteria myFieldCriteria = new VaultCustomQueryCriteria(
Builder.equal(getField("myField", PersistentMyState.class), myValue), StateStatus.ALL);
return stateStatusCriteria.and(myFieldCriteria);

To activate the Hibernate logger, you have to update the log4j.xml file in your cordapp to add the Hibernate configuration, probably something like this:

<Configuration monitorInterval="60">
<Properties>
    <Property name="log-path">PropertiesConfiguration</Property>
</Properties>
<Appenders>
    <Console name="Console-Appender" target="SYSTEM_OUT">
        <PatternLayout>
            <pattern>
                [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
            </pattern>>
        </PatternLayout>
    </Console>
</Appenders>
<Loggers>
    <Logger name="org.hibernate.SQL" level="debug" additivity="false">
        <AppenderRef ref="Console-Appender"/>
    </Logger>
    <Logger name="org.hibernate.type.descriptor.sql" level="trace" additivity="false">
        <AppenderRef ref="Console-Appender"/>
    </Logger>
    <Root level="info">
        <AppenderRef ref="Console-Appender"/>
    </Root>
</Loggers>