Comparison and Practical Guide to Java etcd Clients
This article compares popular Java etcd client libraries, evaluates their features, performance, and suitability, and provides a hands‑on tutorial using jetcd with Maven dependencies, code examples for watching and reading keys, and discusses runtime considerations such as thread handling.
Previously I shared a Go implementation of etcd; now I discuss Java clients, noting that Go has the best support while Java options vary in quality, often resembling Web3j in asynchronous design and documentation.
Java Client Comparison
Feature
jetcd
etcd4j
spring-cloud-kubernetes
vertx-etcd-client
Maintainer
etcd-io (CoreOS)
jurmous
Spring Cloud
Eclipse Vert.x
etcd Compatibility
v3 API
mainly v2 API
v3 API
v3 API
Async Support
Yes
Yes
Yes
Yes
Dependency
gRPC
Netty
Spring Cloud
Vert.x
Features
Official support, full functionality
Lightweight, easy to use
Spring Cloud integration
Vert.x ecosystem integration
Use Cases
Large projects needing full features
Simple usage, legacy systems
Spring Cloud projects
Vert.x projects
Watch Support
Yes
Yes
Yes
Yes
Transaction Support
Yes
Limited
Via Spring abstraction
Yes
Performance
High
Medium
Depends on Spring abstraction
High
Community Activity
High
Low
High
Medium
Documentation Quality
Detailed
Average
Detailed
Detailed
Learning Curve
Medium
Low
High (if unfamiliar with Spring)
Medium
Detailed Comparison
jetcd
Heavy dependency (gRPC)
Potentially steep learning curve
Official support, synchronized with etcd releases
Full v3 API support
Excellent performance for large‑scale production
Pros: ...
Cons: ...
etcd4j
Primarily supports v2 API, limited v3 features
Community updates are slower
Not suitable for new projects requiring v3 features
Lightweight and easy to integrate
Simple, intuitive API
Pros: ...
Cons: ...
spring-cloud-kubernetes
Depends on Spring ecosystem, unsuitable for non‑Spring projects
May introduce unnecessary complexity for simple etcd usage
Deep integration with Spring Cloud and Kubernetes
Provides service discovery and configuration management
Pros: ...
Cons: ...
vertx-etcd-client
Bound to Vert.x, not ideal for non‑Vert.x projects
Smaller community
Integrates with Vert.x ecosystem
Non‑blocking API, suitable for high‑concurrency scenarios
Pros: ...
Cons: ...
Java Client Practice
Below I choose jetcd as the implementation library and add the following Maven dependencies:
<dependency>
<groupId>io.etcd</groupId>
<artifactId>jetcd-core</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>If you encounter a Exception in thread "main" java.lang.NoClassDefFoundError, verify server version, gRPC version, client version, and missing dependencies.
The following example demonstrates watching a key and performing basic write/read operations using jetcd:
package com.funtest.temp
import com.funtester.frame.SourceCode
import io.etcd.jetcd.ByteSequence
import io.etcd.jetcd.Client
import io.etcd.jetcd.Watch
import io.etcd.jetcd.kv.GetResponse
import io.etcd.jetcd.watch.WatchEvent
import java.nio.charset.Charset
import java.nio.charset.StandardCharsets
import java.util.concurrent.CompletableFuture
class TtcdTest extends SourceCode {
static Charset defaultCharset = StandardCharsets.UTF_8
// Create client, connect to etcd
static def client = Client.builder().endpoints("http://localhost:2379").build()
static def kVClient = client.getKVClient()
static def watchClient = client.getWatchClient()
/**
* Watch key changes in etcd and print them
*/
static watch() {
def key = toByteSequence("key")
Watch.Listener listener = Watch.listener(watchResponse -> {
for (WatchEvent event : watchResponse.getEvents()) {
println("watch change ------------------")
println("Event type: " + event.getEventType())
println("Key: " + event.getKeyValue().getKey().toString(StandardCharsets.UTF_8))
println("Value: " + event.getKeyValue().getValue().toString(StandardCharsets.UTF_8))
}
})
watchClient.watch(key, listener)
}
/**
* Write and read data
*/
static writeRead() {
kVClient.put(toByteSequence("key"), toByteSequence("FunTester")).get()
CompletableFuture<GetResponse> getFuture = kVClient.get(toByteSequence("key"))
GetResponse response = getFuture.get()
println("Value: " + response.getKvs().get(0).getValue().toString())
}
/**
* Convert String to ByteSequence
*/
static ByteSequence toByteSequence(String str, Charset = defaultCharset) {
return ByteSequence.from(str, defaultCharset);
}
}Execute the two methods:
public static void main(String[] args) {
watch();
writeRead();
}Console output shows the expected watch event and value retrieval, but the JVM does not exit even after calling client.close(), leaving several RUNNABLE threads and a fork‑join pool, similar to issues seen with Web3j and Netty.
Server Feature Test Performance Test Topics Java, Groovy, Go, Python Unit & White‑box & Tools Collection Testing Strategies, Bugs, Crawlers, UI Automation Testing Theory Soup Community Highlights & Video Collection
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
