{"id":13767452,"url":"https://github.com/msemys/esjc","last_synced_at":"2025-05-10T22:31:52.965Z","repository":{"id":4061202,"uuid":"51838075","full_name":"msemys/esjc","owner":"msemys","description":"EventStore Java Client","archived":false,"fork":false,"pushed_at":"2023-05-01T14:54:31.000Z","size":1053,"stargazers_count":108,"open_issues_count":15,"forks_count":27,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-11-17T02:34:44.857Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/msemys.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-02-16T13:34:53.000Z","updated_at":"2024-03-31T14:17:25.000Z","dependencies_parsed_at":"2023-07-05T20:46:21.883Z","dependency_job_id":null,"html_url":"https://github.com/msemys/esjc","commit_stats":{"total_commits":647,"total_committers":10,"mean_commits":64.7,"dds":0.04945904173106641,"last_synced_commit":"e975b0d51d7f16f25fb1afda48c795fe5e2373b4"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msemys%2Fesjc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msemys%2Fesjc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msemys%2Fesjc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msemys%2Fesjc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/msemys","download_url":"https://codeload.github.com/msemys/esjc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253492529,"owners_count":21916959,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T16:01:08.770Z","updated_at":"2025-05-10T22:31:50.119Z","avatar_url":"https://github.com/msemys.png","language":"Java","funding_links":[],"categories":["Clients by language"],"sub_categories":["JVM"],"readme":"# EventStore Java Client \n\n[![Build Status](https://app.travis-ci.com/msemys/esjc.svg?branch=master)](https://app.travis-ci.com/msemys/esjc)\n[![Version](https://img.shields.io/maven-central/v/com.github.msemys/esjc.svg?label=version)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.github.msemys%22%20AND%20a%3A%22esjc%22)\n[![Javadocs](https://www.javadoc.io/badge/com.github.msemys/esjc.svg)](https://www.javadoc.io/doc/com.github.msemys/esjc) \n\nThis is [EventStore](https://geteventstore.com/) driver for Java, that uses [Netty](http://netty.io/) for network communication and [GSON](https://github.com/google/gson) for object serialization/deserialization to JSON (e.g.: stream metadata, cluster information dto). Client logic implementation is the same as in the original client for .NET platform.\n\n## Requirements\n\n* Java 8\n* EventStore 4.0.0 - 5.0.11 (esjc v2)\n* EventStore 3.2.0 - 3.9.4 (esjc v1)\n\n\n## Maven Dependency\n\n* EventStore v4 (or higher) compatible\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.msemys\u003c/groupId\u003e\n    \u003cartifactId\u003eesjc\u003c/artifactId\u003e\n    \u003cversion\u003e2.6.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n* EventStore v3 compatible\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.msemys\u003c/groupId\u003e\n    \u003cartifactId\u003eesjc\u003c/artifactId\u003e\n    \u003cversion\u003e1.8.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n\n## Build and run tests\n```\n$ ./scripts/generate-ssl-cert.sh\n$ docker-compose up -d\n$ mvn clean verify\n```\n\n## Usage\n\n### Creating a Client Instance\n\nClient instances are created using a builder class. The examples below demonstrate how to create default client with singe-node and cluster-node configuration.\n\n\n* creates a single-node client\n\n```java\nEventStore eventstore = EventStoreBuilder.newBuilder()\n    .singleNodeAddress(\"127.0.0.1\", 1113)\n    .userCredentials(\"admin\", \"changeit\")\n    .build();\n```\n\n* creates a cluster-node client (using gossip seeds)\n\n```java\nEventStore eventstore = EventStoreBuilder.newBuilder()\n    .clusterNodeUsingGossipSeeds(cluster -\u003e cluster\n        .gossipSeedEndpoints(asList(\n            new InetSocketAddress(\"127.0.0.1\", 2113),\n            new InetSocketAddress(\"127.0.0.1\", 2213),\n            new InetSocketAddress(\"127.0.0.1\", 2313))))\n    .userCredentials(\"admin\", \"changeit\")\n    .build();\n```\n\n* creates a cluster-node client (using dns)\n\n```java\nEventStore eventstore = EventStoreBuilder.newBuilder()\n    .clusterNodeUsingDns(cluster -\u003e cluster.dns(\"mycluster.com\"))\n    .userCredentials(\"admin\", \"changeit\")\n    .build();\n```\n\nDriver uses full-duplex communication channel to server. It is recommended that only one instance per application is created.\n\n### SSL\n\nIn order to use secure channel between the client and server, first of all we need to enable SSL on server side by providing TCP secure port and server certificate.\n\n* create private key file and self-signed certificate request (for testing purposes)\n\n```\nopenssl req \\\n  -x509 -sha256 -nodes -days 365 -subj \"/CN=test.com\" \\\n  -newkey rsa:2048 -keyout domain.pem -out domain.csr\n```\n\n* export private key file and self-signed certificate request to PKCS#12 archive\n\n```\nopenssl pkcs12 -export -inkey domain.pem -in domain.csr -out domain.p12\n```\n\n* start server with encrypted TCP connection \n\n```\n./run-node.sh --ext-secure-tcp-port 1119 --certificate-file domain.p12\n```\n\nNow we are ready to connect to single-node or cluster-node using secure channel. On the client side we are able to\nverify server certificate (check either signing certificate or CN and expiration date only) or accept any server\ncertificate without verification.\n\n```java\n// creates a client with secure connection to server whose certificate is trusted by the given certificate file\nEventStore eventstore = EventStoreBuilder.newBuilder()\n    .singleNodeAddress(\"127.0.0.1\", 1119)\n    .useSslConnection(new File(\"domain.csr\"))\n    .userCredentials(\"admin\", \"changeit\")\n    .build();\n\n// creates a client with secure connection to server whose certificate Common Name (CN) matches 'test.com'\nEventStore eventstore = EventStoreBuilder.newBuilder()\n    .singleNodeAddress(\"127.0.0.1\", 1119)\n    .useSslConnection(\"test.com\")\n    .userCredentials(\"admin\", \"changeit\")\n    .build();\n\n// creates a client with secure connection to server without certificate verification\nEventStore eventstore = EventStoreBuilder.newBuilder()\n    .singleNodeAddress(\"127.0.0.1\", 1119)\n    .useSslConnection()\n    .userCredentials(\"admin\", \"changeit\")\n    .build();\n```\n\n### API Examples\n\nAll operations are handled fully asynchronously and returns [`CompletableFuture\u003cT\u003e`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html). For asynchronous result handling you could use [`whenComplete((result, throwable) -\u003e { ... })`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#whenComplete-java.util.function.BiConsumer-) or [`thenAccept(result -\u003e { ... })`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#thenAccept-java.util.function.Consumer-) methods on created future object. To handle result synchronously simply use [`get()`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#get--) or [`join()`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#join--) methods on future object.\n\n```java\n// handles result asynchronously\neventstore.appendToStream(\"foo\", ExpectedVersion.ANY, asList(\n    EventData.newBuilder().type(\"bar\").jsonData(\"{ a : 1 }\").build(),\n    EventData.newBuilder().type(\"baz\").jsonData(\"{ b : 2 }\").build())\n).thenAccept(r -\u003e System.out.println(r.logPosition));\n\n// handles result synchronously\neventstore.appendToStream(\"foo\", ExpectedVersion.ANY, asList(\n    EventData.newBuilder().type(\"bar\").jsonData(\"{ a : 1 }\").build(),\n    EventData.newBuilder().type(\"baz\").jsonData(\"{ b : 2 }\").build())\n).thenAccept(r -\u003e System.out.println(r.logPosition)).get();\n```\n\n#### Writing events\n\n```java\neventstore.appendToStream(\"foo\", ExpectedVersion.ANY, asList(\n    EventData.newBuilder()\n        .type(\"bar\")\n        .data(new byte[]{1, 2, 3, 4, 5})\n        .metadata(new byte[]{6, 7, 8, 9, 0})\n        .build(),\n    EventData.newBuilder()\n        .eventId(UUID.randomUUID())\n        .type(\"baz\")\n        .data(\"dummy content\")\n        .build(),\n    EventData.newBuilder()\n        .type(\"qux\")\n        .jsonData(\"{ a : 1 }\")\n        .build())\n).thenAccept(r -\u003e System.out.println(r.logPosition));\n```\n\n```java\neventstore.appendToStream(\"foo\", 2,\n    EventData.newBuilder()\n        .type(\"quux\")\n        .data(new byte[0])\n        .metadata(new byte[0])\n        .build()\n).thenAccept(r -\u003e System.out.println(r.logPosition));\n```\n\n```java\neventstore.tryAppendToStream(\"foo\", ExpectedVersion.ANY,\n    EventData.newBuilder()\n        .type(\"corge\")\n        .build()\n).thenAccept(r -\u003e {\n    if (r.status == WriteStatus.Success) {\n        System.out.println(r.logPosition);\n    } else {\n        System.err.println(r.status);\n    }\n});\n```\n\n#### Transactional writes\n\n```java\ntry (Transaction t = eventstore.startTransaction(\"foo\", ExpectedVersion.ANY).get()) {\n    t.write(EventData.newBuilder().type(\"bar\").jsonData(\"{ a : 1 }\").build());\n    t.write(EventData.newBuilder().type(\"baz\").jsonData(\"{ b : 2 }\").build());\n    t.write(asList(\n        EventData.newBuilder().type(\"qux\").jsonData(\"{ c : 3 }\").build(),\n        EventData.newBuilder().type(\"quux\").jsonData(\"{ d : 4 }\").build())\n    );\n    t.commit();\n} catch (Exception e) {\n    e.printStackTrace();\n}\n```\n\n```java\neventstore.startTransaction(\"foo\", ExpectedVersion.ANY).thenAccept(t -\u003e {\n    t.write(EventData.newBuilder().type(\"bar\").jsonData(\"{ a : 1 }\").build());\n    t.write(EventData.newBuilder().type(\"baz\").jsonData(\"{ b : 2 }\").build());\n    t.write(asList(\n        EventData.newBuilder().type(\"qux\").jsonData(\"{ c : 3 }\").build(),\n        EventData.newBuilder().type(\"quux\").jsonData(\"{ d : 4 }\").build())\n    );\n    t.rollback();\n});\n```\n\n#### Reading a single event\n\n```java\neventstore.readEvent(\"foo\", 1, false).thenAccept(e -\u003e\n    System.out.format(\"id: '%s'; type: '%s'; data: '%s'\",\n        e.event.originalEvent().eventId,\n        e.event.originalEvent().eventType,\n        e.event.originalEvent().data));\n```\n\n#### Reading stream events forwards\n\n```java\neventstore.readStreamEventsForward(\"foo\", 10, 5, false).thenAccept(e -\u003e\n    e.events.forEach(i -\u003e System.out.format(\"#%d  id: '%s'; type: '%s'; data: '%s'\\n\",\n        i.originalEvent().eventNumber,\n        i.originalEvent().eventId,\n        i.originalEvent().eventType,\n        new String(i.originalEvent().data))));\n```\n\n#### Reading stream events backwards\n\n```java\neventstore.readStreamEventsBackward(\"foo\", 10, 5, false).thenAccept(e -\u003e\n    e.events.forEach(i -\u003e System.out.format(\"#%d  id: '%s'; type: '%s'; data: '%s'\\n\",\n        i.originalEvent().eventNumber,\n        i.originalEvent().eventId,\n        i.originalEvent().eventType,\n        new String(i.originalEvent().data))));\n```\n\n#### Reading all events forwards\n\n```java\neventstore.readAllEventsForward(Position.START, 10, false).thenAccept(e -\u003e\n    e.events.forEach(i -\u003e System.out.format(\"@%s  id: '%s'; type: '%s'; data: '%s'\\n\",\n        i.originalPosition,\n        i.originalEvent().eventId,\n        i.originalEvent().eventType,\n        new String(i.originalEvent().data))));\n```\n\n#### Reading all events backwards\n\n```java\neventstore.readAllEventsBackward(Position.END, 10, false).thenAccept(e -\u003e\n    e.events.forEach(i -\u003e System.out.format(\"@%s  id: '%s'; type: '%s'; data: '%s'\\n\",\n        i.originalPosition,\n        i.originalEvent().eventId,\n        i.originalEvent().eventType,\n        new String(i.originalEvent().data))));\n```\n\n#### Iterates over stream events forward to the end of stream\n\n```java\neventstore.iterateStreamEventsForward(\"foo\", 10, 500, false).forEachRemaining(e -\u003e\n    System.out.format(\"#%d  id: '%s'; type: '%s'; data: '%s'\\n\",\n        e.originalEvent().eventNumber,\n        e.originalEvent().eventId,\n        e.originalEvent().eventType,\n        new String(e.originalEvent().data)));\n```\n\n#### Iterates over stream events backward to the beginning of stream\n\n```java\neventstore.iterateStreamEventsBackward(\"foo\", 10, 500, false).forEachRemaining(e -\u003e\n    System.out.format(\"#%d  id: '%s'; type: '%s'; data: '%s'\\n\",\n        e.originalEvent().eventNumber,\n        e.originalEvent().eventId,\n        e.originalEvent().eventType,\n        new String(e.originalEvent().data)));\n```\n\n#### Iterates over all events forward to the end of ALL stream\n\n```java\neventstore.iterateAllEventsForward(Position.START, 500, false).forEachRemaining(e -\u003e\n    System.out.format(\"@%s  id: '%s'; type: '%s'; data: '%s'\\n\",\n        e.originalPosition,\n        e.originalEvent().eventId,\n        e.originalEvent().eventType,\n        new String(e.originalEvent().data)));\n```\n\n#### Iterates over all events backward to the beginning of ALL stream\n\n```java\neventstore.iterateAllEventsBackward(Position.END, 500, false).forEachRemaining(e -\u003e\n    System.out.format(\"@%s  id: '%s'; type: '%s'; data: '%s'\\n\",\n        e.originalPosition,\n        e.originalEvent().eventId,\n        e.originalEvent().eventType,\n        new String(e.originalEvent().data)));\n```\n\n#### Streaming events forward to the end of stream\n\n```java\neventstore.streamEventsForward(\"foo\", 10, 500, false)\n    .filter(e -\u003e e.originalEvent().eventType.equals(\"bar\"))\n    .forEach(e -\u003e System.out.format(\"#%d  id: '%s'; type: '%s'; data: '%s'\\n\",\n        e.originalEvent().eventNumber,\n        e.originalEvent().eventId,\n        e.originalEvent().eventType,\n        new String(e.originalEvent().data)));\n```\n\n#### Streaming events backward to the beginning of stream\n\n```java\neventstore.streamEventsBackward(\"foo\", 10, 500, false)\n    .filter(e -\u003e e.originalEvent().eventType.equals(\"bar\"))\n    .forEach(e -\u003e System.out.format(\"#%d  id: '%s'; type: '%s'; data: '%s'\\n\",\n        e.originalEvent().eventNumber,\n        e.originalEvent().eventId,\n        e.originalEvent().eventType,\n        new String(e.originalEvent().data)));\n```\n\n#### Streaming all events forward to the end of ALL stream\n\n```java\neventstore.streamAllEventsForward(Position.START, 500, false)\n    .filter(e -\u003e !e.originalEvent().eventType.startsWith(\"$\"))\n    .forEach(e -\u003e System.out.format(\"@%s  id: '%s'; type: '%s'; data: '%s'\\n\",\n        e.originalPosition,\n        e.originalEvent().eventId,\n        e.originalEvent().eventType,\n        new String(e.originalEvent().data)));\n```\n\n#### Streaming all events backward to the beginning of ALL stream\n\n```java\neventstore.streamAllEventsBackward(Position.END, 500, false)\n    .filter(e -\u003e !e.originalEvent().eventType.startsWith(\"$\"))\n    .forEach(e -\u003e System.out.format(\"@%s  id: '%s'; type: '%s'; data: '%s'\\n\",\n        e.originalPosition,\n        e.originalEvent().eventId,\n        e.originalEvent().eventType,\n        new String(e.originalEvent().data)));\n```\n\n#### Subscribes to stream (volatile subscription)\n\n```java\nCompletableFuture\u003cSubscription\u003e volatileSubscription = eventstore.subscribeToStream(\"foo\", false,\n    new VolatileSubscriptionListener() {\n        @Override\n        public void onEvent(Subscription subscription, ResolvedEvent event) {\n            System.out.println(event.originalEvent().eventType);\n        }\n\n        @Override\n        public void onClose(Subscription subscription, SubscriptionDropReason reason, Exception exception) {\n            System.out.println(\"Subscription closed: \" + reason);\n        }\n    });\n\nvolatileSubscription.get().close();\n```\n\n```java\nCompletableFuture\u003cSubscription\u003e volatileSubscription = eventstore.subscribeToStream(\"foo\", false, (s, e) -\u003e\n    System.out.println(e.originalEvent().eventType)\n);\n\nvolatileSubscription.get().close();\n```\n\n#### Subscribes to ALL stream (volatile subscription)\n\n```java\nCompletableFuture\u003cSubscription\u003e volatileSubscription = eventstore.subscribeToAll(false,\n    new VolatileSubscriptionListener() {\n        @Override\n        public void onEvent(Subscription subscription, ResolvedEvent event) {\n            System.out.println(event.originalEvent().eventType);\n        }\n\n        @Override\n        public void onClose(Subscription subscription, SubscriptionDropReason reason, Exception exception) {\n            System.out.println(\"Subscription closed: \" + reason);\n        }\n    });\n\nvolatileSubscription.get().close();\n```\n\n```java\nCompletableFuture\u003cSubscription\u003e volatileSubscription = eventstore.subscribeToAll(false, (s, e) -\u003e \n    System.out.println(e.originalEvent().eventType)\n);\n\nvolatileSubscription.get().close();\n```\n\n#### Subscribes to stream from event number (catch-up subscription)\n\n```java\nCatchUpSubscription catchupSubscription = eventstore.subscribeToStreamFrom(\"foo\", 3L,\n    new CatchUpSubscriptionListener() {\n        @Override\n        public void onLiveProcessingStarted(CatchUpSubscription subscription) {\n            System.out.println(\"Live processing started!\");\n        }\n\n        @Override\n        public void onEvent(CatchUpSubscription subscription, ResolvedEvent event) {\n            System.out.println(event.originalEvent().eventType);\n        }\n\n        @Override\n        public void onClose(CatchUpSubscription subscription, SubscriptionDropReason reason, Exception exception) {\n            System.out.println(\"Subscription closed: \" + reason);\n        }\n    });\n\ncatchupSubscription.close();\n```\n\n```java\nCatchUpSubscription catchupSubscription = eventstore.subscribeToStreamFrom(\"foo\", 3L, (s, e) -\u003e\n    System.out.println(e.originalEvent().eventType)\n);\n\ncatchupSubscription.close();\n```\n\n#### Subscribes to ALL stream from event position (catch-up subscription)\n\n```java\nCatchUpSubscription catchupSubscription = eventstore.subscribeToAllFrom(Position.START,\n    new CatchUpSubscriptionListener() {\n        @Override\n        public void onLiveProcessingStarted(CatchUpSubscription subscription) {\n            System.out.println(\"Live processing started!\");\n        }\n\n        @Override\n        public void onEvent(CatchUpSubscription subscription, ResolvedEvent event) {\n            System.out.println(event.originalEvent().eventType);\n        }\n\n        @Override\n        public void onClose(CatchUpSubscription subscription, SubscriptionDropReason reason, Exception exception) {\n            System.out.println(\"Subscription closed: \" + reason);\n        }\n    });\n\ncatchupSubscription.close();\n```\n\n```java\nCatchUpSubscription catchupSubscription = eventstore.subscribeToAllFrom(Position.of(1, 1), (s, e) -\u003e\n    System.out.println(e.originalEvent().eventType)\n);\n\ncatchupSubscription.close();\n```\n\n#### Subscribes to persistent subscription\n\n```java\nCompletableFuture\u003cPersistentSubscription\u003e persistentSubscription = eventstore.subscribeToPersistent(\"foo\", \"group\", \n    new PersistentSubscriptionListener() {\n        @Override\n        public void onEvent(PersistentSubscription subscription, RetryableResolvedEvent event) {\n            System.out.println(event.originalEvent().eventType);\n        }\n    \n        @Override\n        public void onClose(PersistentSubscription subscription, SubscriptionDropReason reason, Exception exception) {\n            System.out.println(\"Subscription closed: \" + reason);\n        }\n    });\n\npersistentSubscription.get().close();\n```\n\n```java\nCompletableFuture\u003cPersistentSubscription\u003e persistentSubscription = eventstore.subscribeToPersistent(\"foo\", \"group\", (s, e) -\u003e\n    System.out.println(e.originalEvent().eventType)\n);\n\npersistentSubscription.get().stop(Duration.ofSeconds(3));\n```\n\n#### Creates persistent subscription\n\n```java\neventstore.createPersistentSubscription(\"foo\", \"group\", PersistentSubscriptionSettings.newBuilder()\n    .resolveLinkTos(false)\n    .historyBufferSize(20)\n    .liveBufferSize(10)\n    .minCheckPointCount(10)\n    .maxCheckPointCount(1000)\n    .checkPointAfter(Duration.ofSeconds(2))\n    .maxRetryCount(500)\n    .maxSubscriberCount(5)\n    .messageTimeout(Duration.ofSeconds(30))\n    .readBatchSize(500)\n    .startFromCurrent()\n    .timingStatistics(false)\n    .namedConsumerStrategy(SystemConsumerStrategy.ROUND_ROBIN)\n    .build()\n).thenAccept(r -\u003e System.out.println(r.status));\n```\n\n```java\neventstore.createPersistentSubscription(\"bar\", \"group\").thenAccept(r -\u003e System.out.println(r.status));\n```\n\n#### Updates persistent subscription\n\n```java\neventstore.updatePersistentSubscription(\"foo\", \"group\", PersistentSubscriptionSettings.newBuilder()\n    .maxRetryCount(200)\n    .readBatchSize(100)\n    .build()\n).thenAccept(r -\u003e System.out.println(r.status));\n```\n\n#### Deletes persistent subscription\n\n```java\neventstore.deletePersistentSubscription(\"bar\", \"group\").thenAccept(r -\u003e System.out.println(r.status));\n```\n\n#### Deletes stream\n\n```java\neventstore.deleteStream(\"bar\", ExpectedVersion.ANY).thenAccept(r -\u003e System.out.println(r.logPosition));\n```\n\n#### Sets stream metadata\n\n```java\neventstore.setStreamMetadata(\"foo\", ExpectedVersion.ANY, StreamMetadata.newBuilder()\n    .aclReadRoles(asList(\"eric\", \"kyle\", \"stan\", \"kenny\"))\n    .cacheControl(Duration.ofMinutes(10))\n    .maxAge(Duration.ofDays(1))\n    .customProperty(\"baz\", \"dummy text\")\n    .customProperty(\"bar\", 2)\n    .customProperty(\"quux\", 3.4)\n    .customProperty(\"quuux\", true)\n    .build()\n).thenAccept(r -\u003e System.out.println(r.logPosition));\n```\n\n```java\neventstore.setStreamMetadata(\"foo\", ExpectedVersion.ANY, StreamMetadata.empty())\n    .thenAccept(r -\u003e System.out.println(r.logPosition));\n```\n\n#### Gets stream metadata\n\n```java\neventstore.getStreamMetadata(\"foo\").thenAccept(r -\u003e\n    System.out.format(\"deleted: %s, version: %s, stream: %s\\nmetadata: %s\\n\",\n        r.isStreamDeleted,\n        r.metastreamVersion,\n        r.stream,\n        r.streamMetadata.toJson()));\n```\n\n```java\neventstore.getStreamMetadataAsRawBytes(\"foo\").thenAccept(r -\u003e\n    System.out.format(\"deleted: %s, version: %s, stream: %s\\nmetadata-bytes: %s\\n\",\n        r.isStreamDeleted,\n        r.metastreamVersion,\n        r.stream,\n        r.streamMetadata));\n```\n\n#### Sets system settings\n\n```java\nStreamAcl userStreamAcl = StreamAcl.newBuilder()\n    .readRoles(asList(\"eric\", \"kyle\", \"stan\", \"kenny\"))\n    .writeRoles(asList(\"butters\"))\n    .deleteRoles(asList(\"$admins\"))\n    .metaReadRoles(asList(\"victoria\", \"mackey\"))\n    .metaWriteRoles(asList(\"randy\"))\n    .build();\n\nStreamAcl systemStreamAcl = StreamAcl.newBuilder()\n    .readRoles(asList(\"$admins\"))\n    .writeRoles(asList(\"$all\"))\n    .deleteRoles(asList(\"$admins\"))\n    .metaWriteRoles(asList(\"$all\"))\n    .build();\n\neventstore.setSystemSettings(SystemSettings.newBuilder()\n    .userStreamAcl(userStreamAcl)\n    .systemStreamAcl(systemStreamAcl)\n    .build()\n).thenAccept(r -\u003e System.out.println(r.logPosition));\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsemys%2Fesjc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmsemys%2Fesjc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsemys%2Fesjc/lists"}