diff --git a/api/src/main/java/com/github/streamshub/console/api/model/JsonApiMeta.java b/api/src/main/java/com/github/streamshub/console/api/model/JsonApiMeta.java
index d936aba34..b2afff22c 100644
--- a/api/src/main/java/com/github/streamshub/console/api/model/JsonApiMeta.java
+++ b/api/src/main/java/com/github/streamshub/console/api/model/JsonApiMeta.java
@@ -9,6 +9,11 @@
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
+/**
+ * Base class for JSON API meta data attached to the document root, resources, or relationships.
+ *
+ * @see JSON API Document Structure, 7.5 Meta Information
+ */
@Schema(additionalProperties = Object.class)
public class JsonApiMeta {
diff --git a/api/src/main/java/com/github/streamshub/console/api/model/JsonApiRelationship.java b/api/src/main/java/com/github/streamshub/console/api/model/JsonApiRelationship.java
index 49ccf44df..ffa38d432 100644
--- a/api/src/main/java/com/github/streamshub/console/api/model/JsonApiRelationship.java
+++ b/api/src/main/java/com/github/streamshub/console/api/model/JsonApiRelationship.java
@@ -6,6 +6,12 @@
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
+/**
+ * Representation of a JSON API resource relationship linking a resource to another or
+ * providing meta information about the relationship.
+ *
+ * @see JSON API Document Structure, 7.2.2.2 Relationships
+ */
@JsonInclude(value = Include.NON_NULL)
public class JsonApiRelationship implements HasLinks, HasMeta {
diff --git a/api/src/main/java/com/github/streamshub/console/api/support/KafkaContext.java b/api/src/main/java/com/github/streamshub/console/api/support/KafkaContext.java
index 51dec27ac..b5dae1e55 100644
--- a/api/src/main/java/com/github/streamshub/console/api/support/KafkaContext.java
+++ b/api/src/main/java/com/github/streamshub/console/api/support/KafkaContext.java
@@ -85,6 +85,11 @@ public void close() {
if (admin != null) {
admin.close();
}
+ /*
+ * Do not close the registry context when the KafkaContext has client-provided
+ * credentials. I.e., only close when the context is global (with configured
+ * credentials).
+ */
if (applicationScoped && schemaRegistryContext != null) {
try {
schemaRegistryContext.close();
@@ -154,6 +159,13 @@ public Optional tokenUrl() {
.map(KafkaListenerAuthenticationOAuth::getTokenEndpointUri));
}
+ /**
+ * The SchemaRegistryContext contains a per-Kafka registry client
+ * and key/value SerDes classes to be used to handle message browsing.
+ *
+ * The client and SerDes instances will be kept open and reused until
+ * the parent KafkaContext is disposed of at application shutdown.
+ */
public class SchemaRegistryContext implements Closeable {
private final RegistryClient registryClient;
private final MultiformatDeserializer keyDeserializer;
diff --git a/api/src/main/java/com/github/streamshub/console/api/support/serdes/ArtifactReferences.java b/api/src/main/java/com/github/streamshub/console/api/support/serdes/ArtifactReferences.java
index 74cff29c4..eaa7b213b 100644
--- a/api/src/main/java/com/github/streamshub/console/api/support/serdes/ArtifactReferences.java
+++ b/api/src/main/java/com/github/streamshub/console/api/support/serdes/ArtifactReferences.java
@@ -17,6 +17,10 @@
import io.apicurio.registry.resolver.strategy.ArtifactReference;
+/**
+ * Support methods to serialize and deserialize instances of {@link ArtifactReference}
+ * to a string suitable for use as a referencing in a URL.
+ */
public class ArtifactReferences {
private static final Logger LOGGER = Logger.getLogger(ArtifactReferences.class);
diff --git a/api/src/main/java/com/github/streamshub/console/api/support/serdes/AvroDatumProvider.java b/api/src/main/java/com/github/streamshub/console/api/support/serdes/AvroDatumProvider.java
index b983ef7ab..e418512e2 100644
--- a/api/src/main/java/com/github/streamshub/console/api/support/serdes/AvroDatumProvider.java
+++ b/api/src/main/java/com/github/streamshub/console/api/support/serdes/AvroDatumProvider.java
@@ -18,6 +18,10 @@
import io.apicurio.registry.serde.avro.DefaultAvroDatumProvider;
+/**
+ * Provides a reader and writer to convert JSON to and from Avro format using a provided
+ * Avro schema.
+ */
public class AvroDatumProvider extends DefaultAvroDatumProvider {
@Override
public DatumWriter createDatumWriter(RecordData data, Schema schema) {
@@ -65,7 +69,7 @@ public RecordData read(RecordData reuse, Decoder in) throws IOException {
writer.write(datum, jsonEncoder);
jsonEncoder.flush();
- return new RecordData(buffer.toByteArray(), null);
+ return new RecordData(buffer.toByteArray());
}
@Override
diff --git a/api/src/main/java/com/github/streamshub/console/api/support/serdes/AvroDeserializer.java b/api/src/main/java/com/github/streamshub/console/api/support/serdes/AvroDeserializer.java
index 906c997b8..80827337b 100644
--- a/api/src/main/java/com/github/streamshub/console/api/support/serdes/AvroDeserializer.java
+++ b/api/src/main/java/com/github/streamshub/console/api/support/serdes/AvroDeserializer.java
@@ -9,6 +9,10 @@
import io.apicurio.registry.resolver.SchemaResolver;
import io.apicurio.registry.serde.avro.AvroKafkaDeserializer;
+/**
+ * Simple subclass of {@link AvroKafkaDeserializer} to make the {@code readData}
+ * methods public.
+ */
class AvroDeserializer extends AvroKafkaDeserializer {
AvroDeserializer(SchemaResolver schemaResolver) {
super();
diff --git a/api/src/main/java/com/github/streamshub/console/api/support/serdes/ForceCloseable.java b/api/src/main/java/com/github/streamshub/console/api/support/serdes/ForceCloseable.java
index 905590d1a..d7009b9f9 100644
--- a/api/src/main/java/com/github/streamshub/console/api/support/serdes/ForceCloseable.java
+++ b/api/src/main/java/com/github/streamshub/console/api/support/serdes/ForceCloseable.java
@@ -2,6 +2,12 @@
import java.io.IOException;
+/**
+ * The de-/serializers in this package are re-used between requests and have made
+ * their {@code close} methods no-ops. This interface is implemented by each to perform
+ * the actual close operations when a {@link com.github.streamshub.console.api.support.KafkaContext}
+ * is disposed.
+ */
public interface ForceCloseable {
void forceClose() throws IOException;
diff --git a/api/src/main/java/com/github/streamshub/console/api/support/serdes/MultiformatDeserializer.java b/api/src/main/java/com/github/streamshub/console/api/support/serdes/MultiformatDeserializer.java
index 902b8bee3..49173ce9a 100644
--- a/api/src/main/java/com/github/streamshub/console/api/support/serdes/MultiformatDeserializer.java
+++ b/api/src/main/java/com/github/streamshub/console/api/support/serdes/MultiformatDeserializer.java
@@ -27,6 +27,20 @@
import io.apicurio.registry.types.ArtifactType;
import io.apicurio.registry.utils.protobuf.schema.ProtobufSchema;
+/**
+ * Deserializer that supports reading Avro, Protobuf, and raw bytes.
+ *
+ * If an Apicurio Registry client is provided, the deserializer attempts to find
+ * a schema using an identifier found in the message or its headers. If an
+ * identifier is found and a schema is also found, either Avro or Protobuf
+ * deserialization will take place by delegating to the Apicurio deserializer
+ * for each type.
+ *
+ * Otherwise, the data will be returned as-is to the client of the Consumer
+ * using this deserializer. Warning information will be provided for the reason
+ * a raw message is returned if the deserializer detects the presence of a
+ * schema identifier.
+ */
public class MultiformatDeserializer extends AbstractKafkaDeserializer