Skip to main content
ElastiCORE 3.0 is a release candidate: 3.0.261022-rc1 on Maven Central. Projects on the 2.2 line: see the 2.2 documentation.
Version: 3.0

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.

model/entity.yml
  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
WhereIs it thereValue
Entity meta:e.hasMeta("nodelete")e.metaValue("topic") → "petstore.order"
Fieldf.hasDsl("pii")f.dslValue("search") → "like"
The same word several timese.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, @example and @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 - @pi is 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.

CallResult
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.

blueprint/petstore/env.yml
elasticore:
config:
domainName: petstore
…
ps:
maxPageSize: 500 # team rule ps-model-check: no @expose(n) above this
CodeReads
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.