Protobuf serialization for pre-existing objects with runtime schema generation and polymorphic type handling
—
Core functionality for creating, registering, and managing runtime schemas for Java classes. The RuntimeSchema class serves as the main entry point for all schema operations and provides both creation and optimization capabilities.
Primary methods for obtaining schemas for Java classes, with automatic caching and type safety.
/**
* Get or create a cached schema for the specified class using the default ID strategy
* @param typeClass The class to create a schema for
* @return Schema instance for the class
*/
public static <T> Schema<T> getSchema(Class<T> typeClass);
/**
* Get or create a cached schema for the specified class with a custom ID strategy
* @param typeClass The class to create a schema for
* @param strategy Custom ID strategy for polymorphic type handling
* @return Schema instance for the class
*/
public static <T> Schema<T> getSchema(Class<T> typeClass, IdStrategy strategy);
/**
* Create a new RuntimeSchema instance for the specified class
* @param typeClass The class to create a schema for
* @return New RuntimeSchema instance
*/
public static <T> RuntimeSchema<T> createFrom(Class<T> typeClass);
/**
* Create a new RuntimeSchema instance with custom ID strategy
* @param typeClass The class to create a schema for
* @param strategy Custom ID strategy for polymorphic type handling
* @return New RuntimeSchema instance
*/
public static <T> RuntimeSchema<T> createFrom(Class<T> typeClass, IdStrategy strategy);
/**
* Create a new RuntimeSchema instance with field exclusions using String array
* @param typeClass The class to create a schema for
* @param exclusions Array of field names to exclude from the schema
* @param strategy Custom ID strategy for polymorphic type handling
* @return New RuntimeSchema instance
*/
public static <T> RuntimeSchema<T> createFrom(Class<T> typeClass, String[] exclusions, IdStrategy strategy);
/**
* Create a new RuntimeSchema instance with field exclusions
* @param typeClass The class to create a schema for
* @param exclusions Set of field names to exclude from the schema
* @param strategy Custom ID strategy for polymorphic type handling
* @return New RuntimeSchema instance
*/
public static <T> RuntimeSchema<T> createFrom(Class<T> typeClass, Set<String> exclusions, IdStrategy strategy);
/**
* Create a new RuntimeSchema instance with custom field mappings
* @param typeClass The class to create a schema for
* @param declaredFields Map of field names to custom field mappings
* @param strategy Custom ID strategy for polymorphic type handling
* @return New RuntimeSchema instance
*/
public static <T> RuntimeSchema<T> createFrom(Class<T> typeClass, Map<String, String> declaredFields, IdStrategy strategy);Constructor methods and public fields available on RuntimeSchema instances.
/**
* Constructor for RuntimeSchema with reflection-based constructor
* @param typeClass The class this schema represents
* @param fields Collection of field definitions
* @param constructor Java constructor for creating instances
*/
public RuntimeSchema(Class<T> typeClass, Collection<Field<T>> fields, Constructor<T> constructor);
/**
* Constructor for RuntimeSchema with custom instantiator
* @param typeClass The class this schema represents
* @param fields Collection of field definitions
* @param instantiator Custom instantiator for creating instances
*/
public RuntimeSchema(Class<T> typeClass, Collection<Field<T>> fields, Instantiator<T> instantiator);
/**
* Public field providing access to the instantiator
* Used for optimized object creation
*/
public final Instantiator<T> instantiator;Usage Examples:
import io.protostuff.runtime.RuntimeSchema;
import io.protostuff.runtime.DefaultIdStrategy;
import io.protostuff.Schema;
import java.util.Set;
// Basic schema creation
Schema<User> userSchema = RuntimeSchema.getSchema(User.class);
// Schema with custom strategy
IdStrategy strategy = new DefaultIdStrategy(IdStrategy.ENUMS_BY_NAME);
Schema<User> customSchema = RuntimeSchema.getSchema(User.class, strategy);
// Create schema instance directly
RuntimeSchema<User> runtimeSchema = RuntimeSchema.createFrom(User.class);
// Exclude sensitive fields using String array
String[] exclusionsArray = {"password", "ssn"};
RuntimeSchema<User> filteredSchema1 = RuntimeSchema.createFrom(
User.class, exclusionsArray, strategy
);
// Exclude sensitive fields using Set
Set<String> exclusionsSet = Set.of("password", "ssn");
RuntimeSchema<User> filteredSchema2 = RuntimeSchema.createFrom(
User.class, exclusionsSet, strategy
);
// Access instantiator for optimized object creation
RuntimeSchema<User> schema = RuntimeSchema.createFrom(User.class);
Instantiator<User> instantiator = schema.instantiator;
// Use instantiator for fast object creation
User user1 = instantiator.newInstance();
User user2 = instantiator.newInstance();Performance optimization methods for pre-registering schemas and mapping inheritance hierarchies.
/**
* Pre-register a schema for the specified class for improved performance
* @param typeClass The class to register
* @return true if registration was successful, false if already registered
*/
public static <T> boolean register(Class<T> typeClass);
/**
* Register a custom schema for the specified class
* @param typeClass The class to register
* @param schema Custom schema implementation
* @return true if registration was successful, false if already registered
*/
public static <T> boolean register(Class<T> typeClass, Schema<T> schema);
/**
* Map a concrete class to its base class for inheritance handling
* @param baseClass The base/parent class
* @param typeClass The concrete/child class
* @return true if mapping was successful
*/
public static <T> boolean map(Class<? super T> baseClass, Class<T> typeClass);
/**
* Check if a class has been registered
* @param typeClass The class to check
* @return true if the class is registered
*/
public static boolean isRegistered(Class<?> typeClass);
/**
* Check if a class has been registered with a specific strategy
* @param typeClass The class to check
* @param strategy The ID strategy to check against
* @return true if the class is registered with the specified strategy
*/
public static boolean isRegistered(Class<?> typeClass, IdStrategy strategy);Usage Examples:
// Pre-register for performance
RuntimeSchema.register(User.class);
RuntimeSchema.register(Order.class);
RuntimeSchema.register(Product.class);
// Register custom schema
Schema<SpecialObject> customSchema = new MyCustomSchema();
RuntimeSchema.register(SpecialObject.class, customSchema);
// Map inheritance hierarchy
RuntimeSchema.map(Animal.class, Dog.class);
RuntimeSchema.map(Animal.class, Cat.class);
RuntimeSchema.map(Vehicle.class, Car.class);
// Check registration status
if (!RuntimeSchema.isRegistered(User.class)) {
RuntimeSchema.register(User.class);
}Important constants for field number validation and schema configuration.
/**
* Minimum valid protobuf tag/field number
*/
public static final int MIN_TAG_VALUE = 1;
/**
* Maximum valid protobuf tag/field number (2^29 - 1)
*/
public static final int MAX_TAG_VALUE = 536870911;
/**
* Threshold for using hash-based field maps instead of array-based maps
*/
public static final int MIN_TAG_FOR_HASH_FIELD_MAP = 100;Methods available on RuntimeSchema instances for field access and schema information.
/**
* Get the Java class this schema represents
* @return The class type
*/
public Class<T> typeClass();
/**
* Get the message name for this schema
* @return Message name string
*/
public String messageName();
/**
* Get the full message name for this schema
* @return Full message name string
*/
public String messageFullName();
/**
* Get field by its protobuf field number
* @param number The field number
* @return Field instance or null if not found
*/
public Field<T> getFieldByNumber(int number);
/**
* Get field by its name
* @param fieldName The field name
* @return Field instance or null if not found
*/
public Field<T> getFieldByName(String fieldName);
/**
* Get the total number of fields in this schema
* @return Field count
*/
public int getFieldCount();
/**
* Get all fields as a list
* @return List of all fields
*/
public List<Field<T>> getFields();
/**
* Get the field name for a given field number
* @param number The field number
* @return Field name or null if not found
*/
public String getFieldName(int number);
/**
* Get the field number for a given field name
* @param name The field name
* @return Field number or 0 if not found
*/
public int getFieldNumber(String name);
/**
* Get the pipe schema for streaming operations
* @return Pipe schema instance
*/
public Pipe.Schema<T> getPipeSchema();
/**
* Create a new instance of the schema's type
* @return New instance of T
*/
public T newMessage();
/**
* Check if a message instance is fully initialized
* @param message The message to check
* @return true if initialized
*/
public boolean isInitialized(T message);Usage Examples:
RuntimeSchema<User> schema = RuntimeSchema.createFrom(User.class);
// Access schema information
Class<User> userClass = schema.typeClass();
String messageName = schema.messageName();
int fieldCount = schema.getFieldCount();
// Field access
Field<User> nameField = schema.getFieldByName("name");
Field<User> ageField = schema.getFieldByNumber(2);
List<Field<User>> allFields = schema.getFields();
// Create new instances
User newUser = schema.newMessage();
// Check field mappings
String fieldName = schema.getFieldName(1);
int fieldNumber = schema.getFieldNumber("email");Protostuff Runtime automatically assigns field numbers based on field discovery order, but you can control this through:
createFrom with custom field mappingscreateFrom with exclusions to skip specific fieldsregister() for better performancegetSchema() automatically caches schemas, reuse the same Schema instancesmap() to establish inheritance relationships for polymorphic serialization// Application startup: register all schemas
public class SchemaRegistry {
static {
RuntimeSchema.register(User.class);
RuntimeSchema.register(Order.class);
RuntimeSchema.register(Product.class);
// Inheritance mappings
RuntimeSchema.map(BaseEntity.class, User.class);
RuntimeSchema.map(BaseEntity.class, Order.class);
}
}
// Service layer: use cached schemas
public class SerializationService {
private static final Schema<User> USER_SCHEMA = RuntimeSchema.getSchema(User.class);
public void processUser(User user) {
// Use USER_SCHEMA for serialization operations
}
}
// Dynamic schema creation with filtering
public <T> Schema<T> createFilteredSchema(Class<T> clazz, Set<String> sensitiveFields) {
return RuntimeSchema.createFrom(clazz, sensitiveFields, RuntimeEnv.ID_STRATEGY);
}Install with Tessl CLI
npx tessl i tessl/maven-io-protostuff--protostuff-runtime