원클릭으로
state-change-slice
Generate commands, events, aggregates, REST controllers (POST), and tests for STATE_CHANGE slices
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Generate commands, events, aggregates, REST controllers (POST), and tests for STATE_CHANGE slices
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | state-change-slice |
| description | Generate commands, events, aggregates, REST controllers (POST), and tests for STATE_CHANGE slices |
A STATE_CHANGE slice modifies aggregate state through commands and events. It generates:
domain/commands)events)domain)<context>/slices/<slicename>)Note: STATE_CHANGE slices do NOT generate projections. Those belong to STATE_VIEW slices.
REST Controller (POST) → Command → Aggregate (@CommandHandler) → Event
Location: src/main/java/de/eventmodelers/domain/commands/<CommandName>Command.java
package de.eventmodelers.domain.commands;
import de.eventmodelers.common.Command;
import org.axonframework.modelling.command.TargetAggregateIdentifier;
import java.util.UUID;
public record <CommandName>Command(
@TargetAggregateIdentifier UUID aggregateId
// Add fields from slice command definition
) implements Command {}
Location: src/main/java/de/eventmodelers/events/<EventName>Event.java
package de.eventmodelers.events;
import de.eventmodelers.common.Event;
import java.util.UUID;
public record <EventName>Event(
UUID aggregateId
// Add fields from slice event definition
) implements Event {}
Location: src/main/java/de/eventmodelers/domain/<Aggregate>Aggregate.java
For new aggregate (createsAggregate: true or first command):
@CreationPolicy(AggregateCreationPolicy.ALWAYS)
@CommandHandler
public CommandResult handle(<CommandName>Command command) {
AggregateLifecycle.apply(
new <EventName>Event(
command.aggregateId()
// Map command fields to event fields
)
);
return new CommandResult(command.aggregateId(), AggregateLifecycle.getVersion());
}
For existing aggregate:
@CommandHandler
public CommandResult handle(<CommandName>Command command) {
// Business validation logic
AggregateLifecycle.apply(
new <EventName>Event(
command.aggregateId()
// Map command fields to event fields
)
);
return new CommandResult(command.aggregateId(), AggregateLifecycle.getVersion());
}
@EventSourcingHandler
public void on(<EventName>Event event) {
this.aggregateId = event.aggregateId();
// Update other state fields
}
Location: src/main/java/de/eventmodelers/<context>/slices/<slicename>/<SliceName>Controller.java
package de.eventmodelers.<context>.slices.<slicename>;
import de.eventmodelers.domain.commands.<CommandName>Command;
import de.eventmodelers.common.CommandResult;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
@RestController
@RequestMapping("/api/<context>")
public class <SliceName>Controller {
private final CommandGateway commandGateway;
public <SliceName>Controller(CommandGateway commandGateway) {
this.commandGateway = commandGateway;
}
@PostMapping("/<resource>")
public ResponseEntity<CommandResult> execute(@RequestBody <CommandName>Command command) {
var result = commandGateway.sendAndWait(command);
return ResponseEntity.ok(result);
}
@GetMapping("/debug/<command-name-kebab-case>")
public ResponseEntity<CommandResult> debug(
@RequestParam(required = false) UUID aggregateId,
@RequestParam <Type> <fieldName>
// Add @RequestParam for each command field
) {
var command = new <CommandName>Command(
aggregateId != null ? aggregateId : UUID.randomUUID(),
<fieldName>
// Map all parameters to command
);
var result = commandGateway.sendAndWait(command);
return ResponseEntity.ok(result);
}
}
Debug endpoint notes:
/debug/register-customer) to avoid conflicts with STATE_VIEW endpointsaggregateId is optional - generates a new UUID if not provided@RequestParamLocation: src/test/java/de/eventmodelers/<context>/slices/<slicename>/<CommandName>Test.java
package de.eventmodelers.<context>.slices.<slicename>;
import de.eventmodelers.domain.<Aggregate>Aggregate;
import de.eventmodelers.domain.commands.<CommandName>Command;
import de.eventmodelers.events.<EventName>Event;
import org.axonframework.test.aggregate.AggregateTestFixture;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.UUID;
class <CommandName>Test {
private AggregateTestFixture<<Aggregate>Aggregate> fixture;
@BeforeEach
void setUp() {
fixture = new AggregateTestFixture<>(<Aggregate>Aggregate.class);
}
@Test
void <specTitleAsCamelCase>() {
var aggregateId = UUID.randomUUID();
fixture
.given(/* events from spec.given */)
.when(new <CommandName>Command(aggregateId, /* fields from spec.when */))
.expectSuccessfulHandlerExecution()
.expectEvents(new <EventName>Event(aggregateId, /* fields from spec.then */));
}
}
| Slice Type | Java Type |
|---|---|
| UUID | UUID |
| String | String |
| Date | LocalDate |
| Integer | Integer |
| Boolean | Boolean |
| Decimal | BigDecimal |
| Multiple cardinality | List |
| optional: true | @Nullable T |
Location: src/main/java/de/eventmodelers/<context>/ProcessingGroups.java
package de.eventmodelers.<context>;
public final class ProcessingGroups {
public static final String <CONTEXT> = "<CONTEXT>";
private ProcessingGroups() {}
}
Generate event-driven automation processors for AUTOMATION slices
Generate projection integration tests from STATE_VIEW specifications
Transform slice definitions from config.json into executable Java code
Generate read models, projectors, queries, and REST controllers (GET) for STATE_VIEW slices