Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
87d3111
Add codegen module with event-modeling JSON to Akces aggregate code g…
Copilot Mar 26, 2026
550cf72
Add file output test and register codegen in BOM
Copilot Mar 26, 2026
b4872c1
Address code review: consolidate type mapping, validate unknown types
Copilot Mar 26, 2026
640eac5
Add augmented JSON schema and schema validation test suite
Copilot Mar 26, 2026
4532a42
Add compilation test and fix event constructor arg generation
Copilot Mar 26, 2026
98cd6b6
Potential fix for pull request finding 'Useless parameter'
jwijgerd Mar 26, 2026
262e897
Write generated sources to target/generated-test-sources instead of t…
Copilot Mar 26, 2026
a7ef2aa
Compile generated sources into target/test-classes directory
Copilot Mar 26, 2026
099aa09
Add basePackage constructor parameter to AkcesCodeGenerator
Copilot Mar 26, 2026
b3cfe20
Write generated sources to root of generated-test-sources directory
Copilot Mar 26, 2026
75a7756
Add @PIIData annotation support on generated Command and Event field …
Copilot Mar 26, 2026
c040b01
Add SCHEMA_DIFFERENCES.md documenting Akces extensions to the event-m…
Copilot Mar 30, 2026
edf8ae8
Merge branch 'main' into copilot/create-code-generator-for-aggregate
jwijgerd Mar 30, 2026
13b6c39
Add ExternalEventHandler to schema for cross-aggregate @EventHandler …
Copilot Mar 30, 2026
5cfacd9
Remove StateField, reuse Field for aggregate state in codegen schema
Copilot Mar 30, 2026
ba9ff73
Merge branch 'main' into copilot/create-code-generator-for-aggregate
jwijgerd Mar 30, 2026
ebb5a92
Apply suggestions from code review
jwijgerd Mar 30, 2026
32325e1
Move external events from AggregateConfig to Slice as external_events…
Copilot Mar 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
<artifactId>akces-eventcatalog</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsoftwarefoundation.akces</groupId>
<artifactId>akces-codegen</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
184 changes: 184 additions & 0 deletions main/codegen/SCHEMA_DIFFERENCES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# Akces Event Model Schema vs Original Event-Modeling Spec

This document describes the differences between the Akces augmented event-model schema
([`akces-event-model.schema.json`](src/main/resources/akces-event-model.schema.json)) and the
original [event-modeling specification schema](https://github.com/dilgerma/event-modeling-spec/blob/main/eventmodeling.schema.json)
by Martin Dilger.

The Akces schema is a **strict superset** of the original — it preserves every definition from the
original schema unchanged (Slice, Element, ScreenImage, Table, Specification, SpecificationStep,
Comment, Actor, Dependency) and extends it with Akces Framework-specific properties for aggregate
code generation.

---

## Root-Level Changes

| Aspect | Original Schema | Akces Schema |
|---|---|---|
| **title** | *(none)* | `"Akces Event Model Definition"` |
| **description** | *(none)* | Describes the Akces extension of the event-modeling spec |
| **properties** | `slices` | `packageName`, `aggregateConfig`, `slices` |
| **required** | `["slices"]` | `["packageName", "aggregateConfig", "slices"]` |

### New root-level property: `packageName`

```json
"packageName": {
"type": "string",
"description": "The base Java package for generated code"
}
```

Specifies the base Java package name used in the JSON definition. The code generator uses its own
`basePackage` constructor parameter for the generated `package` declarations and directory structure.

### New root-level property: `aggregateConfig`

```json
"aggregateConfig": {
"type": "object",
"description": "Per-aggregate configuration keyed by aggregate name",
"additionalProperties": { "$ref": "#/$defs/AggregateConfig" }
}
```

A map keyed by aggregate name (e.g., `"Account"`, `"Wallet"`) where each value is an
`AggregateConfig` object containing Akces-specific metadata for that aggregate.

---

## New Definition: `AggregateConfig`

Akces-specific configuration for an aggregate, used to generate the state record and aggregate class
annotations.

| Property | Type | Required | Description |
|---|---|---|---|
| `indexed` | `boolean` | No | Whether the aggregate is indexed (maps to `@AggregateInfo(indexed = true)`) |
| `indexName` | `string` | No | The index name (maps to `@AggregateInfo(indexName = "...")`) |
| `generateGDPRKeyOnCreate` | `boolean` | No | Whether to generate a GDPR encryption key on aggregate creation (maps to `@AggregateInfo(generateGDPRKeyOnCreate = true)`) |
| `stateVersion` | `integer` (≥ 1) | No | The version of the aggregate state (maps to `@AggregateStateInfo(version = ...)`) |
| `stateFields` | `Field[]` | **Yes** | The fields of the aggregate state record (reuses the standard `Field` definition) |

**Example:**

```json
"aggregateConfig": {
"Account": {
"indexed": true,
"indexName": "Users",
"generateGDPRKeyOnCreate": true,
"stateVersion": 1,
"stateFields": [
{ "name": "userId", "type": "String", "idAttribute": true },
{ "name": "firstName", "type": "String", "piiData": true },
{ "name": "email", "type": "String", "piiData": true }
]
}
}
```

---

## Modified Definition: `Slice`

The `Slice` definition has one addition compared to the original event-modeling spec schema:

| Property | Type | Required | Description |
|---|---|---|---|
| **`external_events`** *(new)* | `Element[]` | No | External events from other aggregates consumed in this slice |

All other `Slice` properties are unchanged from the original schema.

External events use the same `Element` definition as regular events and commands. They represent
events produced by other aggregates that are consumed by the aggregate in this slice. This is used
for cross-aggregate event handling, particularly for process managers.

**Example** — Wallet aggregate consuming Account's `AccountCreatedEvent`:

```json
{
"id": "create-wallet",
"title": "Create Wallet",
"sliceType": "AUTOMATION",
"aggregates": ["Wallet"],
"commands": [],
"events": [
{
"id": "wallet-created-evt",
"title": "WalletCreated",
"type": "EVENT",
"aggregate": "Wallet",
"createsAggregate": true,
"fields": [
{ "name": "userId", "type": "String", "idAttribute": true }
],
"dependencies": []
}
],
"external_events": [
{
"id": "account-created-ext",
"title": "AccountCreated",
"type": "EVENT",
"aggregate": "Account",
"fields": [
{ "name": "userId", "type": "String", "idAttribute": true }
],
"dependencies": []
}
],
"readmodels": [],
"screens": [],
"processors": [],
"tables": [],
"specifications": []
}
```

---

## Modified Definition: `Field`

The `Field` definition (used in Element fields for commands, events, read models, etc.) has one
addition compared to the original schema:

| Property | Type | Description |
|---|---|---|
| **`piiData`** *(new)* | `boolean` | Whether this field contains PII data requiring GDPR protection |

All other `Field` properties are unchanged from the original schema: `name`, `type`, `example`,
`subfields`, `mapping`, `optional`, `technicalAttribute`, `generated`, `idAttribute`, `schema`,
`cardinality`.

When `piiData: true` is set on a command or event field, the code generator emits the `@PIIData`
annotation on the corresponding record parameter, ensuring GDPR-sensitive fields are consistently
marked across commands, events, and state records.

---

## Unchanged Definitions

The following definitions are **identical** to the original event-modeling spec schema:

- **`Element`** — Represents a command, event, read model, screen, or automation element with fields and dependencies
- **`ScreenImage`** — A screen mockup image reference
- **`Table`** — A data table definition with fields
- **`Specification`** — A BDD-style specification with given/when/then steps
- **`SpecificationStep`** — A step in a specification
- **`Comment`** — A comment with a description
- **`Actor`** — An actor with authentication requirements
- **`Dependency`** — An inbound or outbound dependency between elements

---

## Summary of Additions

| Addition | Location | Purpose |
|---|---|---|
| `packageName` | Root property | Java package name declared in the definition |
| `aggregateConfig` | Root property | Per-aggregate Akces configuration (indexing, GDPR, state fields) |
| `AggregateConfig` | New `$defs` entry | Aggregate-level metadata: indexing, GDPR key generation, state definition |
| `external_events` | Added to `Slice` | External events from other aggregates consumed in a slice |
| `piiData` | Added to `Field` | Marks command/event fields as containing PII data |
81 changes: 81 additions & 0 deletions main/codegen/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!--
~ Copyright 2022 - 2026 The Original Authors
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.elasticsoftwarefoundation.akces</groupId>
<artifactId>akces-framework-main</artifactId>
<version>0.12.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>akces-codegen</artifactId>
<packaging>jar</packaging>

<name>Elastic Software Foundation :: Akces :: Code Generator</name>
<url>https://github.com/elasticsoftwarefoundation/akces-framework</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsoftwarefoundation.akces</groupId>
<artifactId>akces-api</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.erosb</groupId>
<artifactId>everit-json-schema</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<resources>
<resource>
<filtering>false</filtering>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>**/*.json</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<filtering>false</filtering>
<directory>${basedir}/src/test/resources</directory>
<includes>
<include>**/*.json</include>
</includes>
</testResource>
</testResources>
<plugins>
</plugins>
</build>
</project>
Loading
Loading