How can I "Listen" to the TransactionTree in Java

G-d willing

Looking at the PingPong example, can someone please address me to the component that actually subscribes in order to listen to the Daml events? How is it being done exactly?

Thanks,

The part that subscribes to transactions can be found here.

It calls the GetTransactions endpoint which returns a stream and then the onNext method will be called for each stream element.

Thanks @cocreature
And isn’t supposed to be a filter for specific templates that are visible to particular parties? Where is that being set?

It’s set here ex-java-bindings/PingPongProcessor.java at 89052898bbdf9828f08ea039c87095bf65bf679b · digital-asset/ex-java-bindings · GitHub. The filter being used here does not restrict the templates so it will return all contracts visible to party regardless of the template.

G-d willing

So, if I am getting that correctly, I first need to define the request for the “listener” and then activate the listener according to it. Right?

Last, how can I restrict by template?

I wouldn’t define it as two steps, in the end you make a single call to getTransactions and pass two arguments:

  1. Your request, which defines mainly filters and offsets.
  2. Your streamobserver which will get called for each element in the response.

To filter by templates replace the Filters.defaultInstance with something like this:

        TransactionFilterOuterClass.InclusiveFilters.newBuilder()
            .addAllTemplateIds(templateIds)
            .build();
        TransactionFilterOuterClass.Filters.newBuilder().setInclusive(inclusiveFilter).build()

Thanks @cocreature for the answer.
Regarding the two steps, it’s because in the code it is being done in 2 steps as well.
The step, which is defining the request with the filters, is the first one:

        GetTransactionsRequest transactionsRequest = GetTransactionsRequest.newBuilder()
                .setLedgerId(ledgerId)
                .setBegin(LedgerOffset.newBuilder().setBoundary(LedgerBoundary.LEDGER_BEGIN))
                // we use the default filter since we don't want to filter out any contracts
                .setFilter(TransactionFilter.newBuilder().putFiltersByParty(party, Filters.getDefaultInstance()))
                .setVerbose(true)
                .build();

And the second step is creating the observer stream:

        // this StreamObserver reacts to transactions and prints a message if an error occurs or the stream gets closed
        StreamObserver<GetTransactionsResponse> transactionObserver = new StreamObserver<GetTransactionsResponse>() {
            @Override
            public void onNext(GetTransactionsResponse value) {
                value.getTransactionsList().forEach(PingPongProcessor.this::processTransaction);
            }

            @Override
            public void onError(Throwable t) {
                System.err.printf("%s encountered an error while processing transactions!\n", party);
                t.printStackTrace();
            }

            @Override
            public void onCompleted() {
                System.out.printf("%s's transactions stream completed.\n", party);
            }
        };