Examples
Each example starts from the same type definition and shows how a different module uses it — no extra mapping, no separate DTOs.
Shared type definition
All examples below use this single GlobType:
public class ProductType {
public static final GlobType TYPE;
public static final LongField id;
public static final StringField title;
public static final DoubleField price;
public static final BooleanField published;
static {
GlobTypeBuilder b = GlobTypeBuilderFactory.create("Product");
id = b.declareLongField("id");
title = b.declareStringField("title");
price = b.declareDoubleField("price");
published = b.declareBooleanField("published");
TYPE = b.build();
}
}
JSON — globs-gson
Serialize a Glob to JSON and deserialize it back:
import org.globsframework.json.GSonUtils;
// Create a product Glob
MutableGlob product = ProductType.TYPE.instantiate()
.set(ProductType.id, 1L)
.set(ProductType.title, "XPhone")
.set(ProductType.price, 999.0)
.set(ProductType.published, true);
// Encode to JSON
String json = GSonUtils.encode(product, false);
// → {"id":1,"title":"XPhone","price":999.0,"published":true}
// Decode from JSON (only fields present in ProductType.TYPE are read)
Glob decoded = GSonUtils.decode(json, ProductType.TYPE);
String title = decoded.get(ProductType.title); // "XPhone"
Sparse / PATCH semantics
Unset fields are not emitted — so partial updates carry only the fields that changed:
MutableGlob patch = ProductType.TYPE.instantiate()
.set(ProductType.price, 799.0);
// only "price" is set; the others are unset
String patchJson = GSonUtils.encode(patch, false);
// → {"price":799.0}
Database — globs-db
Create a table, insert a row, and query it back:
// Create table from GlobType (no SQL string needed)
sqlConnection.createTable(ProductType.TYPE);
// Insert
sqlConnection.getCreateBuilder(ProductType.TYPE)
.set(ProductType.id, 1L)
.set(ProductType.title, "XPhone")
.set(ProductType.price, 999.0)
.set(ProductType.published, true)
.getRequest().run();
sqlConnection.commit();
// Query with a typed constraint
List<Glob> results = sqlConnection
.getQueryBuilder(ProductType.TYPE,
Constraints.and(
Constraints.equal(ProductType.published, true),
Constraints.lessThan(ProductType.price, 1000.0)))
.selectAll()
.getQuery()
.executeAsGlobs();
for (Glob g : results) {
System.out.println(g.get(ProductType.title) + " — $" + g.get(ProductType.price));
}
HTTP API — globs-http
Declare URL parameters and query parameters as GlobTypes, register
handlers, and start the server. An OpenAPI JSON is generated automatically.
public class UrlParam {
public static GlobType TYPE;
public static LongField id;
static {
GlobTypeBuilder b = GlobTypeBuilderFactory.create("UrlParam");
id = b.declareLongField("id");
TYPE = b.build();
}
}
public class QueryParam {
public static GlobType TYPE;
public static BooleanField includeUnpublished;
static {
GlobTypeBuilder b = GlobTypeBuilderFactory.create("QueryParam");
includeUnpublished = b.declareBooleanField("includeUnpublished");
TYPE = b.build();
}
}
HttpServerRegister server = new HttpServerRegister("ProductAPI/1.0");
server.register("/products/{id}", UrlParam.TYPE)
.get(QueryParam.TYPE, (body, url, query, headers) -> {
long id = url.getNotNull(UrlParam.id);
boolean all = Boolean.TRUE.equals(query.get(QueryParam.includeUnpublished));
// fetch from DB...
Glob product = /* DB lookup */ null;
return CompletableFuture.completedFuture(product);
})
.post(ProductType.TYPE, (body, url, query, headers) -> {
// body is already a Glob of ProductType
return CompletableFuture.completedFuture(body);
});
GlobHttpApacheBuilder builder = new GlobHttpApacheBuilder(server);
builder.startAndWaitForStartup(bootstrap, 8080);
Command-line parsing — globs-commandline
Define your CLI flags as a GlobType; the parser fills them in from
argv and auto-generates --help output from annotations.
public class CliArgs {
public static final GlobType TYPE;
public static final StringField inputFile;
public static final StringField outputFile;
public static final BooleanField verbose;
static {
GlobTypeBuilder b = GlobTypeBuilderFactory.create("CliArgs");
inputFile = b.declareStringField("inputFile");
outputFile = b.declareStringField("outputFile");
verbose = b.declareBooleanField("verbose");
TYPE = b.build();
}
}
public static void main(String[] args) {
Glob parsed = CommandLineParser.parse(args, CliArgs.TYPE);
String input = parsed.get(CliArgs.inputFile);
String output = parsed.get(CliArgs.outputFile);
boolean verbose = Boolean.TRUE.equals(parsed.get(CliArgs.verbose));
// proceed with input / output / verbose ...
}
Invoked as: myapp --input-file data.csv --output-file out.json --verbose
Nested Globs
GlobField and GlobArrayField embed Globs inside Globs —
great for hierarchical data like an order with line items:
public class LineItemType {
public static final GlobType TYPE;
public static final StringField sku;
public static final IntegerField qty;
public static final DoubleField unitPrice;
static {
GlobTypeBuilder b = GlobTypeBuilderFactory.create("LineItem");
sku = b.declareStringField("sku");
qty = b.declareIntegerField("qty");
unitPrice = b.declareDoubleField("unitPrice");
TYPE = b.build();
}
}
public class OrderType {
public static final GlobType TYPE;
public static final StringField orderId;
public static final GlobArrayField items; // ← nested array of LineItemType
static {
GlobTypeBuilder b = GlobTypeBuilderFactory.create("Order");
orderId = b.declareStringField("orderId");
items = b.declareGlobArrayField("items", () -> LineItemType.TYPE);
TYPE = b.build();
}
}
// Build nested structure
MutableGlob line1 = LineItemType.TYPE.instantiate()
.set(LineItemType.sku, "SKU-001")
.set(LineItemType.qty, 2)
.set(LineItemType.unitPrice, 49.99);
MutableGlob order = OrderType.TYPE.instantiate()
.set(OrderType.orderId, "ORD-2024-001")
.set(OrderType.items, new Glob[]{ line1 });
// Serialize the whole tree to JSON in one call
String json = GSonUtils.encode(order, false);
// → {"orderId":"ORD-2024-001","items":[{"sku":"SKU-001","qty":2,"unitPrice":49.99}]}
Dynamic types from JSON schema
When the schema is not known at compile time — e.g. reading a configuration format
defined externally — build a GlobType at runtime:
// Suppose we receive this JSON describing the type
String schemaJson = """
{"name":"Event","fields":[
{"name":"timestamp","type":"Long"},
{"name":"source","type":"String"},
{"name":"payload","type":"String"}
]}
""";
GlobType eventType = GlobTypeDeserializer.parse(schemaJson);
// Now use it exactly like a statically-defined type
Glob event = GSonUtils.decode(incomingJson, eventType);
Field sourceField = eventType.getField("source");
String source = (String) event.getValue(sourceField);