From 159827e3d0e94e02467c6c5de66334921fba407f Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Thu, 15 Jun 2023 13:29:06 +0200 Subject: [PATCH] GH-183 - Initial draft of Spring CLI support --- .../jmolecules/add-aggregate/Aggregate.java | 28 +++++++ .../add-aggregate/AggregateUnitTests.java | 19 +++++ .../jmolecules/add-aggregate/Repository.java | 11 +++ .../RepositoryIntegrationTests.java | 21 ++++++ .../jmolecules/add-aggregate/command.yaml | 15 ++++ .../create-aggregate-and-repository.yaml | 13 ++++ .../commands/jmolecules/init/command.yaml | 15 ++++ .../jmolecules/init/init-jmolecules.yaml | 24 ++++++ .../jmolecules/init/setup-bytebuddy.yaml | 40 ++++++++++ jmolecules-spring-cli/readme.adoc | 74 +++++++++++++++++++ 10 files changed, 260 insertions(+) create mode 100644 jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/Aggregate.java create mode 100644 jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/AggregateUnitTests.java create mode 100644 jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/Repository.java create mode 100644 jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/RepositoryIntegrationTests.java create mode 100644 jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/command.yaml create mode 100644 jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/create-aggregate-and-repository.yaml create mode 100644 jmolecules-spring-cli/.spring/commands/jmolecules/init/command.yaml create mode 100644 jmolecules-spring-cli/.spring/commands/jmolecules/init/init-jmolecules.yaml create mode 100644 jmolecules-spring-cli/.spring/commands/jmolecules/init/setup-bytebuddy.yaml create mode 100644 jmolecules-spring-cli/readme.adoc diff --git a/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/Aggregate.java b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/Aggregate.java new file mode 100644 index 0000000..5774cea --- /dev/null +++ b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/Aggregate.java @@ -0,0 +1,28 @@ +package {{root-package}}.{{module}}; + +import java.util.UUID; + +import org.jmolecules.ddd.types.AggregateRoot; +import org.jmolecules.ddd.types.Identifier; + +import {{root-package}}.{{module}}.{{capitalizeFirst name}}.{{capitalizeFirst name}}Identifier; + + +/** + * A {{capitalizeFirst name}}. + */ +public class {{capitalizeFirst name}} implements AggregateRoot<{{capitalizeFirst name}}, {{capitalizeFirst name}}Identifier> { + + private final {{capitalizeFirst name}}Identifier id; + + public {{capitalizeFirst name}}() { + this.id = new {{capitalizeFirst name}}Identifier(UUID.randomUUID()); + } + + @Override + public {{capitalizeFirst name}}Identifier getId() { + return id; + } + + record {{capitalizeFirst name}}Identifier(UUID id) implements Identifier {} +} diff --git a/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/AggregateUnitTests.java b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/AggregateUnitTests.java new file mode 100644 index 0000000..401da09 --- /dev/null +++ b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/AggregateUnitTests.java @@ -0,0 +1,19 @@ +package {{root-package}}.{{module}}; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {{capitalizeFirst name}}. + */ +class {{capitalizeFirst name}}UnitTests { + + @Test + void createsSimple{{capitalizeFirst name}}Instance() { + + var {{name}} = new {{capitalizeFirst name}}(); + + assertThat({{name}}.getId()).isNotNull(); + } +} diff --git a/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/Repository.java b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/Repository.java new file mode 100644 index 0000000..849bedc --- /dev/null +++ b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/Repository.java @@ -0,0 +1,11 @@ +package {{root-package}}.{{module}}; + +import org.jmolecules.ddd.types.Repository; +import {{root-package}}.{{module}}.{{capitalizeFirst name}}.{{capitalizeFirst name}}Identifier; + +/** + * A repository to manage {{capitalizeFirst name}} instances. + */ +interface {{capitalizeFirst name}}Repository extends Repository<{{capitalizeFirst name}}, {{capitalizeFirst name}}Identifier> { + +} diff --git a/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/RepositoryIntegrationTests.java b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/RepositoryIntegrationTests.java new file mode 100644 index 0000000..d77270c --- /dev/null +++ b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/RepositoryIntegrationTests.java @@ -0,0 +1,21 @@ +package {{root-package}}.{{module}}; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * Integration tests for {{capitalizeFirst name}}Repository. + */ +@SpringBootTest +class {{capitalizeFirst name}}RepositoryIntegrationTests { + + @Autowired {{capitalizeFirst name}}Repository repository; + + @Test + void repositoryBootstrapped() { + assertThat(repository).isNotNull(); + } +} diff --git a/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/command.yaml b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/command.yaml new file mode 100644 index 0000000..46bd60b --- /dev/null +++ b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/command.yaml @@ -0,0 +1,15 @@ +command: + description: Add a jMolecules aggregate + options: + + - name: name + description: The name of the aggregate (camel case) + dataType: string + inputType: text + required: true + + - name: module + description: The name of the module to create the aggregate in. + dataType: string + inputType: text + required: true diff --git a/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/create-aggregate-and-repository.yaml b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/create-aggregate-and-repository.yaml new file mode 100644 index 0000000..76eabb5 --- /dev/null +++ b/jmolecules-spring-cli/.spring/commands/jmolecules/add-aggregate/create-aggregate-and-repository.yaml @@ -0,0 +1,13 @@ +actions: + - generate: + to: src/main/java/{{root-package-dir}}/{{module}}/{{capitalizeFirst name}}.java + from: Aggregate.java + - generate: + to: src/test/java/{{root-package-dir}}/{{module}}/{{capitalizeFirst name}}UnitTests.java + from: AggregateUnitTests.java + - generate: + to: src/main/java/{{root-package-dir}}/{{module}}/{{capitalizeFirst name}}Repository.java + from: Repository.java + - generate: + to: src/test/java/{{root-package-dir}}/{{module}}/{{capitalizeFirst name}}RepositoryIntegrationTests.java + from: RepositoryIntegrationTests.java diff --git a/jmolecules-spring-cli/.spring/commands/jmolecules/init/command.yaml b/jmolecules-spring-cli/.spring/commands/jmolecules/init/command.yaml new file mode 100644 index 0000000..0c232ae --- /dev/null +++ b/jmolecules-spring-cli/.spring/commands/jmolecules/init/command.yaml @@ -0,0 +1,15 @@ +command: + description: Initializes the project to use jMolecules + options: + + - name: with-architecture + description: Which architectural stype to use (onion, hexagonal, clean) + dataType: string + + - name: with-ddd + description: Whether to enable the Domain-Driven Design support + dataType: boolean + + - name: with-codegen + description: Whether to enable the ByteBuddy based code generation for boilerplate persistence + dataType: boolean diff --git a/jmolecules-spring-cli/.spring/commands/jmolecules/init/init-jmolecules.yaml b/jmolecules-spring-cli/.spring/commands/jmolecules/init/init-jmolecules.yaml new file mode 100644 index 0000000..05b59a4 --- /dev/null +++ b/jmolecules-spring-cli/.spring/commands/jmolecules/init/init-jmolecules.yaml @@ -0,0 +1,24 @@ +actions: + - inject-maven-dependency-management: + text: | + + org.jmolecules + jmolecules-bom + 2022.3.0 + pom + import + + - inject-maven-dependency: + text: | + {{#if with-ddd}} + + org.jmolecules.integrations + jmolecules-starter-ddd + + {{/if}} + {{#if with-architecture}} + + org.jmolecules + jmolecules-{{with-architecture}}-architecture + + {{/if}} diff --git a/jmolecules-spring-cli/.spring/commands/jmolecules/init/setup-bytebuddy.yaml b/jmolecules-spring-cli/.spring/commands/jmolecules/init/setup-bytebuddy.yaml new file mode 100644 index 0000000..7bc4842 --- /dev/null +++ b/jmolecules-spring-cli/.spring/commands/jmolecules/init/setup-bytebuddy.yaml @@ -0,0 +1,40 @@ +actions: + - exec: + command: ./mvnw dependency:list | grep 'jakarta.persistence-api' -q + define: + name: jpa-present + - inject-maven-build-plugin: + text: | + {{#if with-codegen}} + + net.bytebuddy + byte-buddy-maven-plugin + 1.14.4 + + true + + + + + transform-extended + + + + + {{/if}} + - inject-maven-dependency: + text: | + {{#if with-codegen}} + {{#if jpa-present = 0}} + + org.jmolecules.integrations + jmolecules-jpa + runtime + + {{/if}} + + org.jmolecules.integrations + jmolecules-bytebuddy-nodep + provided + + {{/if}} diff --git a/jmolecules-spring-cli/readme.adoc b/jmolecules-spring-cli/readme.adoc new file mode 100644 index 0000000..8f5e55a --- /dev/null +++ b/jmolecules-spring-cli/readme.adoc @@ -0,0 +1,74 @@ += Spring CLI Integration + +This module of jMolecules Integration provides integration with https://github.com/spring-projects-experimental/spring-cli[Spring CLI]. + +== Installation + +Run Spring CLI and issue the `command add` command pointing it to this particular module of the repository. + +``` +$ spring +spring:> command add … +``` + +== Usage + +The integration provides the following commands. + +=== Initializing jMolecules + +`jmolecules init` adds all artifacts necessary to the POM of the project, depending on which features you'd like to use. + +``` +NAME + jmolecules init - Initializes the project to use jMolecules + +SYNOPSIS + jmolecules init --with-architecture String --with-ddd Boolean --with-codegen Boolean --help + +OPTIONS + --with-architecture String + Which architectural stype to use (onion, hexagonal, clean) + [Optional] + + --with-ddd Boolean + Whether to enable the Domain-Driven Design support + [Optional] + + --with-codegen Boolean + Whether to enable the ByteBuddy based code generation for boilerplate persistence + [Optional] + + --help or -h + help for jmolecules init + [Optional] +``` + +=== Adding a DDD aggregate to the project + +Adding an aggregate to the project results in three new files generated in the project: + +* The aggregate file implementing `AggregateRoot` using a custom, record-based `Identifier` implementation backed by a `UUID`. +* A repository declaration to persist instances of the aggregate. +* A unit test class for the aggregate itself + +``` +NAME + jmolecules add-aggregate - Add a jMolecules aggregate + +SYNOPSIS + jmolecules add-aggregate [--name String] [--module String] --help + +OPTIONS + --name String + The name of the aggregate (camel case) + [Mandatory] + + --module String + The name of the module to create the aggregate in. + [Mandatory] + + --help or -h + help for jmolecules add-aggregate + [Optional] +```