How to write $tb to metadata from Java-client


I’m trying to write integration test for our software, where in various scenarios we expect a certain set of events to be stored in the eventstore.

In the @Before method of our test, I want to clean up a stream an write certain events to that stream.

I’m having problems with the first part: the clean up of the stream. Based upon what I found here, I trying to use the ‘Truncate Before’ by setting the $tb to the stream metadata.

In order to determine the number for the $tb-value I read the feed of /stream/my-stream and us the number of the first entry (So far I’m fine)

In order to set the $tb I POST to the POST /streams/my-stream/metadata the following message:

and I get “HTTP/1.1 201 Created” with /streams/%24%24my-stream//11"

When I get /streams/my-stream/metadata I see: No 11 / Stream: $$my-stream with correct type and timestamp and as data:

  "$tb": 3 


But when I get /streams/my-stream I still see the list of 4 previous events in the stream.

What more do I need to do or what do I need to change to stop seeing the previous events?

With kind regards,

Marco Beelen

Which java client?

also what version are you running?

Greg (and all others),

First of all I was running the stable 2.0.1 version, in which the $tb isn’t supported at all, so I upgraded to the v3.0.0rc2.

I was trying to write to the metadata stream using the Eventstore.JVM.

Finally I managed to write the metadata properly so that the Eventstore considers a stream to be ‘empty’ again in a Integration Test.

So the problem is solved already. The code which solved the problem for us is appended below.


Marco Beelen

public void truncateBefore(String streamName, Long eventNumber) {

final ActorSystem system = ActorSystem.create();

final Settings settings = new SettingsBuilder()

      .address(new InetSocketAddress(config.getIpAddress(), config.getBinaryPort()))

      .defaultCredentials(config.getLoginName(), config.getLoginPassword())


final ActorRef connection = system.actorOf(ConnectionActor.getProps(settings));

final ActorRef writeResult = system.actorOf(Props.create(WriteResult.class));

String jsonPayload = "{\"$tb\": " + eventNumber + "}";

final EventData event = new EventDataBuilder("$metadata")




final WriteEvents writeEvents = new WriteEventsBuilder("$$" + streamName)




connection.tell(writeEvents, writeResult);


public static class WriteResult extends UntypedActor {

public void onReceive(Object message) throws Exception {

   if (message instanceof Status.Failure) {

       final Status.Failure failure = ((Status.Failure) message);

        System.err.println("Writing to EventStream failed, due to" + failure.cause().getMessage());

        throw (EsException) failure.cause();

     } else if (message instanceof WriteEventsCompleted) {

        final WriteEventsCompleted completed = (WriteEventsCompleted) message;

        final EventNumber.Exact eventNumber = completed.firstEventNumber();

        System.out.println("eventNumber: " + eventNumber);




If you use delete without hard delete it will do this for you internally :slight_smile:

And how would we have to send such a delete command to a stream (or it’s metadata)?

_connection.Delete … or over http a delete.

public Task DeleteStreamAsync(string stream, int expectedVersion, UserCredentials userCredentials = null)

public Task DeleteStreamAsync(string stream, int expectedVersion, bool hardDelete, UserCredentials userCredentials = null)

By default it will truncate unless you specify hard delete

Over http there is a header for harddelete:


Hi Marko,

To delete stream in v3xx or 2xx (example in Scala)

Btw when JVM client released against EventStore 3.0.0 it will have have method WriteEventsBuilder.streamMetadata with some helpers :wink: