README
The
REFCODES.ORGcodes represent a group of artifacts consolidating parts of my work in the past years. Several topics are covered which I consider useful for you, programmers, developers and software engineers.
What is this repository for?
This artifact defines a lightweight canonical schema for representing a system’s runtime state and offers visitor interfaces to export that state in multiple notations.
It helps you understand and diagnose complex object graphs without invasive debugging or excessive logging. You model your data as nested Schema instances, optionally expose a simple Schemable façade on your types, and let visitors render the result.
How do I get set up?
To get up and running, include the following dependency (without the three dots “…”) in your pom.xml:
1
2
3
4
5
6
7
8
9
<dependencies>
...
<dependency>
<artifactId>refcodes-schema</artifactId>
<groupId>org.refcodes</groupId>
<version>3.4.1</version>
</dependency>
...
</dependencies>
The artifact is hosted directly at Maven Central. Jump straight to the source codes at Bitbucket. Read the artifact’s javadoc at javadoc.io.
1
2
3
4
5
6
7
8
9
<dependencies>
...
<dependency>
<artifactId>refcodes-schema-alt-introspection</artifactId>
<groupId>org.refcodes</groupId>
<version>3.4.1</version>
</dependency>
...
</dependencies>
The artifact is hosted directly at Maven Central. Jump straight to the source codes at Bitbucket. Read the artifact’s javadoc at javadoc.io.
How do I get started?
The core pieces are:
-
SchemaA canonical container for diagnostic data. Holds key/value properties, an optional instance reference, and childSchemanodes to form a hierarchy. -
SchemableAn interface for types that can expose their diagnostic view viatoSchema(). -
SchemaVisitor<R>A visitor that traverses aSchematree and produces an output of typeR. Implementations include JSON, XML, and PlantUML exporters.
Canonical model
You capture runtime state as a nested tree of Schema nodes. Each node can store arbitrary properties (key/value), and may have child nodes for contained or related data. This yields a consistent, tool-friendly view across subsystems.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public final class SensorReading implements Schemable {
private final String name;
private final int value;
public SensorReading(String name, int value) {
this.name = name;
this.value = value;
}
@Override
public Schema toSchema() {
return Schema.builder()
.withAlias("sensorReading")
.withInstance(this)
.withDescription("A single sensor reading")
.withProperty("name", name)
.withProperty("value", Integer.toString(value))
.build();
}
}
Composites simply aggregate their children’s Schema:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public final class SensorPanel implements Schemable {
private final List<SensorReading> sensors;
public SensorPanel(List<SensorReading> sensors) {
this.sensors = sensors;
}
@Override
public Schema toSchema() {
var childSchemas = sensors.stream()
.map(Schemable::toSchema)
.toArray(Schema[]::new);
return Schema.builder()
.withAlias("sensorPanel")
.withInstance(this)
.withDescription("Panel with multiple sensors")
.withChildren(childSchemas)
.build()
.withProperty("count", Integer.toString(sensors.size()));
}
}
Export with visitors
Once you have a Schema, you can render it in different formats by supplying the corresponding visitor:
1
2
3
4
5
Schema schema = panel.toSchema();
String json = schema.visit(new JsonVisitor());
String xml = schema.visit(new XmlVisitor());
String puml = schema.visit(new PlantUmlVisitor());
- JSON/XML give you machine-readable diagnostics for pipelines, dashboards, and reports
- PlantUML gives you diagrams that visualize object graphs for faster human understanding
Serving diagnostics via an interface
You can expose diagnostics safely without enabling full debug mode. For example, via Spring Boot Actuator:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component
@WebEndpoint(id = "diagnostics")
public class DiagnosticsEndpoint {
private final Schemable root; // Provide your root of interest
public DiagnosticsEndpoint(Schemable root) { this.root = root; }
@ReadOperation
public WebEndpointResponse<String> plantUml() {
Schema schema = root.toSchema();
String puml = schema.visit(new PlantUmlVisitor());
return new WebEndpointResponse<>(puml, 200, "text/x-plantuml");
}
}
Alternatively, expose the same data via an MBean and access it with JMX tools such as JConsole.
Snippets of interest
Add ad-hoc properties
1
2
3
4
5
6
7
Schema schema = Schema.builder()
.withAlias("job")
.withDescription("Batch job diagnostics")
.build()
.withProperty("id", jobId)
.withProperty("status", status)
.withProperty("durationMs", Long.toString(duration));
Compose hierarchies
1
2
3
4
Schema root = Schema.builder()
.withAlias("orderProcessing")
.withChildren(order.toSchema(), inventory.toSchema(), payment.toSchema())
.build();
Render and persist
1
2
3
4
5
6
String xml = root.visit(new XmlVisitor());
String json = root.visit(new JsonVisitor());
// Write to disk or attach to tickets
Files.writeString(Path.of("diag.xml"), xml);
Files.writeString(Path.of("diag.json"), json);
Visualize with PlantUML
1
2
String puml = root.visit(new PlantUmlVisitor());
// Feed into a PlantUML renderer to produce a diagram for your runbook
Design considerations
-
Separation of concerns Diagnostics are modeled once as a canonical schema. Export formats are independent visitors.
-
Low overhead Simple POJOs implement
Schemable. No heavy dependencies or annotations required. -
Extensibility Add your own
SchemaVisitorfor custom formats or targets. -
Operational safety Expose read-only snapshots via endpoints or JMX without attaching debuggers or flooding logs.
Examples
For examples and usage, please take a look at the according Unit-Tests here.
For examples and usage on the introspection alternative, please take a look at the according Unit-Tests here.
See also
- Output runtime diagnostics data as JSON, XML or PlantUML diagrams
- The canonical model, an ace upon your sleeve
Contribution guidelines
- Report issues
- Finding bugs
- Helping fixing bugs
- Making code and documentation better
- Enhance the code
Who do I talk to?
- Siegfried Steiner (steiner@refcodes.org)
Terms and conditions
The REFCODES.ORG group of artifacts is published under some open source licenses; covered by the refcodes-licensing (org.refcodes group) artifact - evident in each artifact in question as of the pom.xml dependency included in such artifact.
