DSL words and model checks
DSL words of your team's own
ElastiCORE does not treat a word it does not know as an error; it only keeps it. Nothing appears in the generated code, and rules can read it. So your team's concepts can be written straight into the YAML.
Category:
meta: entity @root @editable @expose(20) @access(read=public) @nodelete # an entity word
Customer:
fields:
email: string(100) @email @pii # a field word
PurchaseOrder:
meta: entity @root @expose(20) @event(Placed(total), Shipped, Cancelled) @topic(petstore.order) # a word with a value
| Where | Is it there | Value |
|---|---|---|
Entity meta: | e.hasMeta("nodelete") | e.metaValue("topic") → "petstore.order" |
| Field | f.hasDsl("pii") | f.dslValue("search") → "like" |
| The same word several times | e.metaValues("x") | |
Named attributes @x(a=1, b=2) | f.dslProperty("x", "a"), e.metaText("x") (the text as written) |
Field words are case-insensitive (@PII is also hasDsl("pii")).
When naming one:
- Check whether ElastiCORE already has it - do not rebuild features that exist, such as
@readonly,@restExclude,@exampleand@label. Delete the rule and see: if the output stays the same, it already exists. The list: DSL reference. - Do not clash with words already in use -
@event,@search,@label… If in doubt, use a team prefix (@psTopic). - A typo is silent -
@piis simply ignored. If the word matters, add a check rule as below.
Model checks - ModelCheck
A rule can also write no code and only check the model.
| Call | Result |
|---|---|
ModelCheck.warn(msg) | Prints a warning only, the same message once. The build goes on |
ModelCheck.fail(msg) | Generation runs to the end (so every problem shows at once), then the failures are shown together and the build fails |
@Rule("ps-model-check")
void check(EntitySpec e) {
if (!e.aggregateRoot()) return;
if (!e.commands().isEmpty() && e.events().isEmpty()) {
ModelCheck.warn(String.format(
"[ps] %s takes commands but declares no @event: nothing outside the aggregate hears what happened.",
e.getName()));
}
// A team setting in env.yml: elasticore.config.ps.maxPageSize
String max = e.config("ps.maxPageSize");
String expose = e.metaValue("expose");
if (max != null && expose != null && expose.trim().matches("\\d+")
&& Integer.parseInt(expose.trim()) > Integer.parseInt(max.trim())) {
ModelCheck.fail(String.format(
"[ps] %s pages %s rows at a time (@expose(%s)); the team maximum is ps.maxPageSize=%s.",
e.getName(), expose.trim(), expose.trim(), max.trim()));
}
}
Team settings - config(...)
Values that may differ per project, such as a check's limit, do not belong hard-coded in the rule; put
them under config: in env.yml.
elasticore:
config:
domainName: petstore
…
ps:
maxPageSize: 500 # team rule ps-model-check: no @expose(n) above this
| Code | Reads |
|---|---|
e.config("ps.maxPageSize") | elasticore.config.ps.maxPageSize of that entity's domain - null if absent |
d.config("…"), d.isOn("…") | in a domain rule / whether it is "true" |
The pet store's Country is @expose(300). Lower maxPageSize to 100 and:
[elcore3] the model check failed (1) - fix these and build again:
[ps] Country pages 300 rows at a time (@expose(300)); the team maximum is ps.maxPageSize=100.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':elcore3'.
> Process 'command '…\java.exe'' finished with non-zero exit value 1
At 500 it passes. Generation runs to the end even on failure, so the problems of several entities show at once. Files already made that the DSL no longer makes are not deleted until the check passes.
Do not throw exceptions
An exception inside a rule fails only the one file that rule was writing (ERROR); the rest is
generated, and the run ends with exit code 1. It is hard to tell which file was left out and why. Use
ModelCheck.fail for a problem in the model, and return for a case the rule cannot handle.
In tests
@Test
void aPageAboveTheTeamMaximumFails() {
EntitySpec country = new EntitySpec("Country").domain("petstore", "Petstore").meta("root", "")
.meta("expose", "300").config("ps.maxPageSize", "100")
.field("isoCode", "string(2) @id");
engine().run(country, "entity");
assertEquals(1, ModelCheck.failures().size());
}
@AfterEach
void forget() {
ModelCheck.reset(); // failures are kept per JVM: reset between tests
}
ModelCheck.failures() collects only failures. Warnings are printed to the console, so to test a
warning, capture System.out. More in Testing.