Implementation:Risingwavelabs Risingwave DynFields
| Knowledge Sources | |
|---|---|
| Domains | Reflection, Iceberg, Utilities |
| Language | Java |
| Lines | 428 |
| Last Updated | 2026-02-09 07:00 GMT |
Overview
Utility class providing a builder pattern for dynamically accessing Java fields by reflection, ported from the Apache Iceberg project.
Description
DynFields is a utility class (with a private constructor) that enables runtime field access through Java reflection. It is part of the Apache Iceberg common utilities, included in the RisingWave Iceberg sink connector module. The class provides several nested types:
- UnboundField<T> -- A wrapper around java.lang.reflect.Field that provides typed get(Object target) and set(Object target, T value) operations with exceptions wrapped as RuntimeExceptions. It can be bound to a specific target via bind(Object) or converted to a StaticField via asStatic(). It also provides isStatic() and isAlwaysNull() checks.
- AlwaysNull -- A singleton UnboundField<Void> subclass that always returns null on get and is a no-op on set. Used as a default when no field implementation is found and defaultAlwaysNull() is configured on the builder.
- StaticField<T> -- Wraps an UnboundField for static field access (target is always null).
- BoundField<T> -- Wraps an UnboundField bound to a specific target object for instance field access.
- Builder -- Fluent builder that searches for fields across multiple candidate classes:
- impl(String className, String fieldName) -- Looks up a public field by class name and field name.
- impl(Class<?> targetClass, String fieldName) -- Looks up a public field on a known class.
- hiddenImpl(String className, String fieldName) -- Looks up a private/protected field by class name, making it accessible.
- hiddenImpl(Class<?> targetClass, String fieldName) -- Looks up a private/protected field on a known class, making it accessible.
- defaultAlwaysNull() -- Falls back to AlwaysNull if no implementation is found.
- buildChecked() / build() -- Returns the found UnboundField or throws.
- buildChecked(Object target) / build(Object target) -- Returns a BoundField.
- buildStaticChecked() / buildStatic() -- Returns a StaticField.
- MakeFieldAccessible -- A PrivilegedAction that calls setAccessible(true) on hidden fields.
Usage
Used internally by the Iceberg sink connector for reflective field access required by Iceberg catalog integration, avoiding compile-time coupling to specific Iceberg internal implementations.
Code Reference
Source Location
- Repository: risingwave
- File: java/connector-node/risingwave-sink-iceberg/src/main/java/org/apache/iceberg/common/DynFields.java
- Lines: 1-428
Signature
public class DynFields {
private DynFields() {}
public static class UnboundField<T> {
public T get(Object target);
public void set(Object target, T value);
public BoundField<T> bind(Object target);
public StaticField<T> asStatic();
public boolean isStatic();
public boolean isAlwaysNull();
}
public static class StaticField<T> {
public T get();
public void set(T value);
}
public static class BoundField<T> {
public T get();
public void set(T value);
}
public static Builder builder();
public static class Builder {
public Builder loader(ClassLoader newLoader);
public Builder defaultAlwaysNull();
public Builder impl(String className, String fieldName);
public Builder impl(Class<?> targetClass, String fieldName);
public Builder hiddenImpl(String className, String fieldName);
public Builder hiddenImpl(Class<?> targetClass, String fieldName);
public <T> UnboundField<T> buildChecked() throws NoSuchFieldException;
public <T> BoundField<T> buildChecked(Object target) throws NoSuchFieldException;
public <T> UnboundField<T> build();
public <T> BoundField<T> build(Object target);
public <T> StaticField<T> buildStaticChecked() throws NoSuchFieldException;
public <T> StaticField<T> buildStatic();
}
}
Import
import org.apache.iceberg.common.DynFields;
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| className | String | No | Fully qualified class name to search for the field (resolved via Class.forName) |
| targetClass | Class<?> | No | Class instance to search for the field |
| fieldName | String | Yes | Name of the field to locate |
| target | Object | Varies | Object instance for BoundField binding (required for non-static fields) |
Outputs
| Name | Type | Description |
|---|---|---|
| UnboundField<T> | DynFields.UnboundField | Reflective field accessor not bound to a specific target |
| BoundField<T> | DynFields.BoundField | Reflective field accessor bound to a specific object instance |
| StaticField<T> | DynFields.StaticField | Reflective accessor for static fields |
Exceptions
| Exception | Condition |
|---|---|
| NoSuchFieldException | No matching field found (from buildChecked methods) |
| RuntimeException | No matching field found (from build methods) or illegal access |
| IllegalStateException | Attempting to bind a static field or call asStatic on a non-static field |
| IllegalArgumentException | Target object class is incompatible with the field's declaring class |
Usage Examples
Accessing a Hidden Field
// Access a private field named "internalState" from SomeClass
DynFields.BoundField<String> field = DynFields.builder()
.hiddenImpl(SomeClass.class, "internalState")
.build(someInstance);
String value = field.get();
field.set("newValue");
Accessing a Static Field with Fallback
// Try multiple candidate classes, fall back to AlwaysNull
DynFields.UnboundField<Integer> field = DynFields.builder()
.impl("com.example.NewApi", "VERSION")
.impl("com.example.OldApi", "VERSION")
.defaultAlwaysNull()
.build();
if (!field.isAlwaysNull()) {
Integer version = field.get(null);
}