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

Team rules (rulesets) overview

Every company and team wants something in the generated code.

  • "Our annotation on every aggregate root"
  • "Personal data fields never go out in the response JSON"
  • "A LIKE search needs at least two characters"
  • "A root that publishes events must name its topic - otherwise the build fails"
  • "A message topic constants class for every event"

Edit a generated file by hand and the change disappears on the next generation (a generator's file), or has to be repeated for every entity. Write a rule once instead, and it applies to every domain and every entity on every generation. A rule is a plain Java class, and one method is one rule. ElastiCORE's own Java, Kotlin, DDD and hexagonal generation are all rules of the same kind - a team rule is just one more added after them.

ps-rules/src/main/java/com/example/rules/PetstoreRules.java
public class PetstoreRules implements CodeRules {

/** A field marked @pii in the DSL is accepted in requests but never sent back. */
@Rule(value = "ps-pii", target = "dto")
void pii(EntitySpec dto, FieldSpec field) {
if (field.hasDsl("pii")) {
ctx(dto).field(field).ensure(AnnoCode.of("com.fasterxml.jackson.annotation.JsonProperty")
.valRaw("access", "JsonProperty.Access.WRITE_ONLY"));
}
}
}
blueprint/petstore/model/entity.yml
      email:       string(100) @email @pii     # our team's DSL word
build.gradle
elasticore { rules = ['com.example.rules.PetstoreRules'] }    // added after the bundle
dependencies { elasticore project(':ps-rules') } // the generator's classpath

When to use a rule​

SituationHow
Something for one entity, one fieldCheck the DSL first - DSL reference
Business logic of one entityBy hand in the developer's file - Adding business logic
The same thing on every entity, field and DTO, as a team standardA rule
A DSL word of your team's own (@pii, @topic)Read by a rule
Stopping the build when the model breaks a team ruleA rule (ModelCheck)
A file ElastiCORE does not make, made from the modelA rule + a skeleton (a new target)
Leaving out part of what ElastiCORE makessuppress or a rule

How it works​

./gradlew build runs generation (elcore3) before compiling. Team rules run inside it, after ElastiCORE's default rules, for every file it makes.

entity.yml ─▶ ① read YAML ─▶ ② decide files ─▶ ③ default rules ─▶ ④ team rules ─▶ ⑤ write .java ─▶ ⑥ compile
env.yml (Spec) Customer.java @Entity, PetstoreRules
CustomerDTO.java … @Column …
  • ③ and ④ repeat per file: once when Customer.java is made, again when CustomerDTO.java is made.
  • ④ always comes after ③, so it can remove what the default rules added or add on top of it.
  • A rule does not write the file itself. It says "this annotation on this class" or "this value in this slot"; the generator sorts the imports and writes the file. That is why the same rule applies to Java and Kotlin, and why several rules can contribute to one file.

Every rule has the same shape: read (EntitySpec, FieldSpec - the YAML as written), decide (a plain if), write (ctx(entity) - the file being made).

YAMLRead in a rule
Customer:entity.getName() → "Customer"
meta: entity @root @expose(20)entity.aggregateRoot() → true, entity.metaValue("expose") → "20"
email: string(100) @email @piifield.name() → "email", field.hasDsl("pii") → true
name: string(30)! @search(like)field.required() → true, field.dslValue("search") → "like"

What a rule can do​

WhatAPIPage
Add or remove annotations on classes, fields and methods, add attributesensureClassAnnotation, field(f).ensure/merge/removeAnnotation, method(n).ensureAnnotations and methods
Add a method to a class, leave out an endpointaddMethod, excludeMethodAnnotations and methods
DSL words of your team's ownhasDsl, dslValue, hasMeta, metaValueDSL words and model checks
Warnings, build failures, team settingsModelCheck.warn/fail, config("…")DSL words and model checks
DTO, search, SQL, external integration and enum filestarget = "dto" …Targets
Make new filesArtifactContributor, a .tmpl skeletonMaking new files
Turn default rules off, a bundle per domainsuppress, publisher.rulesTurning off and bundles
Test only the rules, quicklyRuleEngine.run(...).render()Testing
The same ruleset in several projectsship it as a jarPublishing and sharing

Reading order​

  1. Your first ruleset - attach a rules module to the pet store and see the first rule change the generated output
  2. Annotations and methods
  3. DSL words and model checks
  4. Targets
  5. Making new files
  6. Turning default rules off and choosing a bundle
  7. Testing
  8. Publishing and sharing
  9. API reference, Troubleshooting

Every example in these pages was built and run on the pet store project with ElastiCORE 3.0.261022-rc1.