Skip to content

State Services

Overview

Vaultaire’s StateServices provide a simple, consistent API to load, query and track vault states.

StateService implementations are usually auto-generated at build time based on VaultaireStateUtils or VaultaireStateUtilsMixin annotations, i.e. specific to a single ContractState type.

State Services can also decouple you code from ServiceHub and CordaRPCOps by providing constructors for either, thus helping increase code reuse between cordapps and their clients. They also support RPC connection pooling, i.e. provide a constructor that accepts a PoolBoy PoolBoyConnection.

Basic Services

Basic implementations of NodeService and StateService are more limited and/or less easy to use than generated ones but functional nevertheless:

val bookStateService = BasicStateService(
    serviceHubOrRpcOpsOrPoolBoy,
    BookContract.BookState::class.java)

State Services

Vaultaire’s annotation processor will generate optimal StateService implementations, each specific to one of the ContractState-PersistentState pairs found at build-time based on the VaultaireStateUtils or VaultaireStateUtilsMixin annotations found in your code. Service classnames are based on the contract state classname, suffixed by “Service”.

Usage example:

// Create an instance of the generated service type,
// passing a ServiceHub, CordaRPCOps, NodeRpcConnection
// or even a custom StateServiceDelegate
val bookStateService = BookStateService(serviceHub)

// Load a book
bookStateService.getByLinearId(identifier)

// Try finding one by UniqueIdentifier.externalId,
// in this case an ISBN
bookStateService.findByExternalId(isbn)

// Count the book states that match our query criteria
val booksCount = bookStateService.countBy(queryCriteria)

// Query the vault for a results page of the same books
val searchResultsPage: Vault.Page<BookState> = bookStateService.queryBy(
    queryCriteria,
    // Optional PageSpecification or page number/size params
    page,
    // Optional Sort or vararg of Pair<String, Sort.Direction>
    sort)

// Track the vault for book events
val trackResults = bookStateService.queryBy(criteria)

Custom Services

You can also subclass (or, perhaps preferably, use as delegates) generated service types or BasicNodeService, BasicStateService, ExtendedStateService etc. to create custom components.

/** Extend the generated [BookStateService] */
class MyExtendedBookStateService(
        delegate: StateServiceDelegate<BookState>
) : BookStateService(delegate){

    // Add the appropriate constructors
    // to initialize per delegate type:

    /** [CordaRPCOps]-based constructor */
    constructor(
            rpcOps: CordaRPCOps, defaults: StateServiceDefaults = StateServiceDefaults()
    ) : this(StateServiceRpcDelegate(rpcOps, BookState::class.java, defaults))

    /** [ServiceHub]-based constructor */
    constructor(
            serviceHub: ServiceHub, defaults: StateServiceDefaults = StateServiceDefaults()
    ) : this(StateServiceHubDelegate(serviceHub, BookState::class.java, defaults))

    // Custom business methods...
}