Implementation:Apache Paimon Preconditions
| Knowledge Sources | |
|---|---|
| Domains | Utilities, Validation |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
Preconditions provides static utility methods for input validation including null checks, argument validation, state validation, and index bounds checking.
Description
Preconditions is a foundational utility class modelled after Google Guava's Preconditions, designed to reduce external dependencies while providing consistent validation throughout Paimon. The class offers multiple validation methods that throw appropriate exceptions based on the validation type: NullPointerException for null checks, IllegalArgumentException for invalid method arguments, IllegalStateException for invalid object states, and IndexOutOfBoundsException for invalid indexes.
All validation methods support three forms: no error message, simple error message, and template-based error messages with %s placeholder substitution. The template format method is optimized for performance, using a simple StringBuilder approach rather than String.format. It processes %s placeholders sequentially and appends any extra arguments in square brackets, making it suitable for debugging without sacrificing runtime performance.
The class includes special-purpose methods like checkElementIndex for array/list bounds validation and checkCompletedNormally for CompletableFuture validation. By providing these utilities, Paimon maintains consistent error handling patterns across the codebase without introducing heavyweight dependencies like Google Guava.
Usage
Use Preconditions for defensive programming at the beginning of methods to validate inputs, object states, and preconditions. This ensures fast-fail behavior and clear error messages when invalid conditions are detected.
Code Reference
Source Location
- Repository: Apache_Paimon
- File: paimon-api/src/main/java/org/apache/paimon/utils/Preconditions.java
- Lines: 32-307
Signature
public final class Preconditions {
// Null checks
public static <T> T checkNotNull(@Nullable T reference);
public static <T> T checkNotNull(@Nullable T reference, @Nullable String errorMessage);
public static <T> T checkNotNull(T reference, @Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs);
// Argument validation
public static void checkArgument(boolean condition);
public static void checkArgument(boolean condition, @Nullable Object errorMessage);
public static void checkArgument(boolean condition, @Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs);
// State validation
public static void checkState(boolean condition);
public static void checkState(boolean condition, @Nullable Object errorMessage);
public static void checkState(boolean condition, @Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs);
// Index validation
public static void checkElementIndex(int index, int size);
public static void checkElementIndex(int index, int size, @Nullable String errorMessage);
// Future validation
public static void checkCompletedNormally(CompletableFuture<?> future);
}
Import
import org.apache.paimon.utils.Preconditions;
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| reference | T | yes | Object reference to check for null |
| condition | boolean | yes | Condition to validate |
| index | int | yes | Index to validate |
| size | int | yes | Size of collection for index validation |
| future | CompletableFuture<?> | yes | Future to check completion status |
| errorMessage | String | no | Error message for exception |
| errorMessageTemplate | String | no | Template with %s placeholders |
| errorMessageArgs | Object... | no | Arguments for template substitution |
Outputs
| Name | Type | Description |
|---|---|---|
| reference | T | The validated non-null reference (for checkNotNull) |
| exception | RuntimeException | Thrown on validation failure |
Usage Examples
Null Checks
// Basic null check
public void setName(String name) {
this.name = Preconditions.checkNotNull(name);
}
// Null check with message
public void setConfig(Configuration config) {
this.config = Preconditions.checkNotNull(
config,
"Configuration must not be null"
);
}
// Null check with template
public void setField(String fieldName, DataType type) {
this.fieldName = Preconditions.checkNotNull(
fieldName,
"Field name must not be null for type %s",
type
);
}
Argument Validation
// Basic argument check
public void setBucketCount(int count) {
Preconditions.checkArgument(count > 0);
this.bucketCount = count;
}
// Argument check with message
public void setPartitionKeys(List<String> keys) {
Preconditions.checkArgument(
!keys.isEmpty(),
"Partition keys cannot be empty"
);
this.partitionKeys = keys;
}
// Argument check with template
public void validateFieldNames(List<String> fieldNames, List<String> primaryKeys) {
Preconditions.checkArgument(
fieldNames.containsAll(primaryKeys),
"Primary keys %s must be subset of field names %s",
primaryKeys,
fieldNames
);
}
State Validation
// Basic state check
public void write(byte[] data) {
Preconditions.checkState(!closed);
writeInternal(data);
}
// State check with message
public DataType getResultType() {
Preconditions.checkState(
initialized,
"Type system not initialized"
);
return resultType;
}
// State check with template
public void commit() {
Preconditions.checkState(
!committed,
"Transaction %s already committed at %s",
transactionId,
commitTime
);
commitInternal();
}
Index Validation
// Basic index check
public DataField getField(int index) {
Preconditions.checkElementIndex(index, fields.size());
return fields.get(index);
}
// Index check with message
public String getFieldName(int fieldIndex) {
Preconditions.checkElementIndex(
fieldIndex,
fieldNames.size(),
"Invalid field index"
);
return fieldNames.get(fieldIndex);
}
Complex Validation Patterns
// Validate constructor parameters
public TableSchema(long id, List<DataField> fields,
List<String> partitionKeys, List<String> primaryKeys) {
this.id = id;
this.fields = Preconditions.checkNotNull(fields, "Fields must not be null");
this.partitionKeys = Preconditions.checkNotNull(
partitionKeys,
"Partition keys must not be null"
);
this.primaryKeys = Preconditions.checkNotNull(
primaryKeys,
"Primary keys must not be null"
);
Preconditions.checkArgument(
!fields.isEmpty(),
"Schema must have at least one field"
);
Preconditions.checkArgument(
!primaryKeys.isEmpty() || partitionKeys.isEmpty(),
"Table with partition keys must have primary keys"
);
}
Future Validation
// Check future completion
public void waitForCompletion(CompletableFuture<Void> task) {
// Wait for task
task.join();
// Validate it completed normally (not exceptionally)
Preconditions.checkCompletedNormally(task);
// Continue with dependent operations
processResults();
}
Template Formatting Examples
// Single placeholder
Preconditions.checkArgument(
value >= 0,
"Value must be non-negative: %s",
value
);
// Multiple placeholders
Preconditions.checkState(
startTime < endTime,
"Start time %s must be before end time %s",
startTime,
endTime
);
// Extra arguments (appended in square brackets)
Preconditions.checkArgument(
isValid,
"Invalid configuration for %s",
name,
extraDebugInfo,
moreContext
);
// Message: "Invalid configuration for myName [extraDebugInfo, moreContext]"
Method Return with Validation
// Return validated non-null value
public String getRequiredOption(String key) {
return Preconditions.checkNotNull(
options.get(key),
"Required option %s not found",
key
);
}
// Validate and return
public DataField getRequiredField(String fieldName) {
DataField field = nameToField.get(fieldName);
return Preconditions.checkNotNull(
field,
"Field %s not found in schema",
fieldName
);
}