eva4j 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/QUICK_REFERENCE.md +204 -0
- package/README.md +912 -0
- package/USAGE.md +349 -0
- package/bin/eva4j.js +234 -0
- package/config/defaults.json +46 -0
- package/package.json +57 -0
- package/src/commands/add-kafka-client.js +193 -0
- package/src/commands/add-module.js +221 -0
- package/src/commands/create.js +92 -0
- package/src/commands/detach.js +495 -0
- package/src/commands/generate-http-exchange.js +309 -0
- package/src/commands/generate-kafka-event.js +453 -0
- package/src/commands/generate-kafka-listener.js +267 -0
- package/src/commands/generate-resource.js +265 -0
- package/src/commands/generate-usecase.js +198 -0
- package/src/commands/info.js +63 -0
- package/src/generators/base-generator.js +150 -0
- package/src/generators/module-generator.js +48 -0
- package/src/generators/shared-generator.js +153 -0
- package/src/utils/config-manager.js +156 -0
- package/src/utils/context-builder.js +149 -0
- package/src/utils/naming.js +137 -0
- package/src/utils/template-engine.js +55 -0
- package/src/utils/validator.js +159 -0
- package/templates/base/application/Application.java.ejs +27 -0
- package/templates/base/docker/docker-compose.yml.ejs +41 -0
- package/templates/base/gradle/build.gradle.ejs +70 -0
- package/templates/base/gradle/settings.gradle.ejs +1 -0
- package/templates/base/resources/application-develop.yml.ejs +5 -0
- package/templates/base/resources/application-local.yml.ejs +5 -0
- package/templates/base/resources/application-production.yml.ejs +9 -0
- package/templates/base/resources/application-test.yml.ejs +5 -0
- package/templates/base/resources/application.yml.ejs +31 -0
- package/templates/base/resources/parameters/develop/cors.yml.ejs +4 -0
- package/templates/base/resources/parameters/develop/db.yaml.ejs +21 -0
- package/templates/base/resources/parameters/develop/kafka.yml.ejs +26 -0
- package/templates/base/resources/parameters/local/cors.yml.ejs +4 -0
- package/templates/base/resources/parameters/local/db.yaml.ejs +21 -0
- package/templates/base/resources/parameters/local/kafka.yml.ejs +26 -0
- package/templates/base/resources/parameters/production/cors.yml.ejs +4 -0
- package/templates/base/resources/parameters/production/db.yaml.ejs +21 -0
- package/templates/base/resources/parameters/production/kafka.yml.ejs +26 -0
- package/templates/base/root/README.md.ejs +126 -0
- package/templates/base/root/gitignore.ejs +42 -0
- package/templates/http-exchange/Adapter.java.ejs +39 -0
- package/templates/http-exchange/Config.java.ejs +24 -0
- package/templates/http-exchange/FeignClient.java.ejs +23 -0
- package/templates/http-exchange/Port.java.ejs +14 -0
- package/templates/kafka-event/Event.java.ejs +10 -0
- package/templates/kafka-event/KafkaConfigBean.java.ejs +7 -0
- package/templates/kafka-event/KafkaMessageBroker.java.ejs +32 -0
- package/templates/kafka-event/MessageBroker.java.ejs +8 -0
- package/templates/kafka-event/MessageBrokerImplMethod.java.ejs +9 -0
- package/templates/kafka-event/MessageBrokerMethod.java.ejs +1 -0
- package/templates/kafka-listener/KafkaController.java.ejs +34 -0
- package/templates/kafka-listener/ListenerMethod.java.ejs +9 -0
- package/templates/kafka-listener/ValueField.java.ejs +4 -0
- package/templates/module/controller.java.ejs +96 -0
- package/templates/module/exception.java.ejs +18 -0
- package/templates/module/mapper.java.ejs +67 -0
- package/templates/module/model.java.ejs +29 -0
- package/templates/module/package-info.java.ejs +7 -0
- package/templates/module/repository.java.ejs +26 -0
- package/templates/module/request-dto.java.ejs +24 -0
- package/templates/module/response-dto.java.ejs +26 -0
- package/templates/module/service-impl.java.ejs +112 -0
- package/templates/module/service.java.ejs +45 -0
- package/templates/module/update-dto.java.ejs +25 -0
- package/templates/resource/Command.java.ejs +9 -0
- package/templates/resource/CommandHandler.java.ejs +22 -0
- package/templates/resource/Controller.java.ejs +73 -0
- package/templates/resource/Query.java.ejs +12 -0
- package/templates/resource/QueryHandler.java.ejs +31 -0
- package/templates/resource/ResponseDto.java.ejs +6 -0
- package/templates/shared/annotations/ApplicationComponent.java.ejs +9 -0
- package/templates/shared/annotations/DomainComponent.java.ejs +9 -0
- package/templates/shared/annotations/LogAfter.java.ejs +11 -0
- package/templates/shared/annotations/LogBefore.java.ejs +11 -0
- package/templates/shared/annotations/LogExceptions.java.ejs +11 -0
- package/templates/shared/annotations/LogTimer.java.ejs +11 -0
- package/templates/shared/configurations/kafkaConfig/KafkaConfig.java.ejs +49 -0
- package/templates/shared/configurations/loggerConfig/HandlerLogs.java.ejs +56 -0
- package/templates/shared/configurations/securityConfig/SecurityConfig.java.ejs +57 -0
- package/templates/shared/configurations/swaggerConfig/SwaggerConfig.java.ejs +31 -0
- package/templates/shared/configurations/useCaseConfig/UseCaseAutoRegister.java.ejs +51 -0
- package/templates/shared/configurations/useCaseConfig/UseCaseConfig.java.ejs +25 -0
- package/templates/shared/configurations/useCaseConfig/UseCaseContainer.java.ejs +29 -0
- package/templates/shared/configurations/useCaseConfig/UseCaseMediator.java.ejs +38 -0
- package/templates/shared/customExceptions/BadRequestException.java.ejs +11 -0
- package/templates/shared/customExceptions/ConflictException.java.ejs +8 -0
- package/templates/shared/customExceptions/ForbiddenException.java.ejs +8 -0
- package/templates/shared/customExceptions/ImportFileException.java.ejs +6 -0
- package/templates/shared/customExceptions/NotFoundException.java.ejs +8 -0
- package/templates/shared/customExceptions/UnauthorizedException.java.ejs +9 -0
- package/templates/shared/customExceptions/ValidationException.java.ejs +17 -0
- package/templates/shared/errorMessage/ErrorMessage.java.ejs +5 -0
- package/templates/shared/errorMessage/FullErrorMessage.java.ejs +9 -0
- package/templates/shared/errorMessage/ShortErrorMessage.java.ejs +6 -0
- package/templates/shared/eventEnvelope/EventEnvelope.java.ejs +13 -0
- package/templates/shared/eventEnvelope/EventMetadata.java.ejs +24 -0
- package/templates/shared/filters/CorrelationIdFilter.java.ejs +45 -0
- package/templates/shared/handlerException/HandlerExceptions.java.ejs +148 -0
- package/templates/shared/interfaces/Command.java.ejs +4 -0
- package/templates/shared/interfaces/CommandHandler.java.ejs +5 -0
- package/templates/shared/interfaces/Dispatchable.java.ejs +4 -0
- package/templates/shared/interfaces/Handler.java.ejs +4 -0
- package/templates/shared/interfaces/Query.java.ejs +4 -0
- package/templates/shared/interfaces/QueryHandler.java.ejs +5 -0
- package/templates/shared/package-info.java.ejs +8 -0
- package/templates/usecase/command/Command.java.ejs +7 -0
- package/templates/usecase/command/CommandHandler.java.ejs +21 -0
- package/templates/usecase/query/Query.java.ejs +10 -0
- package/templates/usecase/query/QueryHandler.java.ejs +22 -0
- package/templates/usecase/query/ResponseDto.java.ejs +5 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<% if (features.includeDocker && dependencies.includes('data-jpa') && databaseType !== 'h2') { %>version: '3.8'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
<% if (databaseType === 'postgresql') { %> postgres:
|
|
5
|
+
image: postgres:16-alpine
|
|
6
|
+
container_name: <%= artifactId %>-postgres
|
|
7
|
+
environment:
|
|
8
|
+
POSTGRES_DB: <%= databaseName %>
|
|
9
|
+
POSTGRES_USER: <%= databaseUsername %>
|
|
10
|
+
POSTGRES_PASSWORD: <%= databasePassword %>
|
|
11
|
+
ports:
|
|
12
|
+
- "5432:5432"
|
|
13
|
+
volumes:
|
|
14
|
+
- postgres-data:/var/lib/postgresql/data
|
|
15
|
+
networks:
|
|
16
|
+
- <%= artifactId %>-network
|
|
17
|
+
<% } else if (databaseType === 'mysql') { %> mysql:
|
|
18
|
+
image: mysql:8.0
|
|
19
|
+
container_name: <%= artifactId %>-mysql
|
|
20
|
+
environment:
|
|
21
|
+
MYSQL_DATABASE: <%= databaseName %>
|
|
22
|
+
MYSQL_USER: <%= databaseUsername %>
|
|
23
|
+
MYSQL_PASSWORD: <%= databasePassword %>
|
|
24
|
+
MYSQL_ROOT_PASSWORD: <%= databasePassword %>
|
|
25
|
+
ports:
|
|
26
|
+
- "3306:3306"
|
|
27
|
+
volumes:
|
|
28
|
+
- mysql-data:/var/lib/mysql
|
|
29
|
+
networks:
|
|
30
|
+
- <%= artifactId %>-network
|
|
31
|
+
<% } %>
|
|
32
|
+
|
|
33
|
+
volumes:
|
|
34
|
+
<% if (databaseType === 'postgresql') { %> postgres-data:
|
|
35
|
+
<% } else if (databaseType === 'mysql') { %> mysql-data:
|
|
36
|
+
<% } %>
|
|
37
|
+
|
|
38
|
+
networks:
|
|
39
|
+
<%= artifactId %>-network:
|
|
40
|
+
driver: bridge
|
|
41
|
+
<% } %>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
plugins {
|
|
2
|
+
id 'java'
|
|
3
|
+
id 'org.springframework.boot' version '<%= springBootVersion %>'
|
|
4
|
+
id 'io.spring.dependency-management' version '<%= dependencyManagementVersion %>'
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
group = '<%= groupId %>'
|
|
8
|
+
version = '<%= version %>'
|
|
9
|
+
|
|
10
|
+
java {
|
|
11
|
+
toolchain {
|
|
12
|
+
languageVersion = JavaLanguageVersion.of(<%= javaVersion %>)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
configurations {
|
|
17
|
+
compileOnly {
|
|
18
|
+
extendsFrom annotationProcessor
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
repositories {
|
|
23
|
+
mavenCentral()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
dependencyManagement {
|
|
27
|
+
imports {
|
|
28
|
+
<% if (typeof isDetached === 'undefined' || !isDetached) { %> mavenBom "org.springframework.modulith:spring-modulith-bom:<%= springModulithVersion %>"
|
|
29
|
+
<% } %> mavenBom "org.springframework.cloud:spring-cloud-dependencies:<%= springCloudVersion %>"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
dependencies {
|
|
34
|
+
implementation 'org.springframework.boot:spring-boot-starter'
|
|
35
|
+
|
|
36
|
+
<% if (typeof isDetached === 'undefined' || !isDetached) { %> // Spring Modulith - Mandatory
|
|
37
|
+
implementation 'org.springframework.modulith:spring-modulith-starter-core'
|
|
38
|
+
implementation 'org.springframework.modulith:spring-modulith-starter-jpa'
|
|
39
|
+
testImplementation 'org.springframework.modulith:spring-modulith-starter-test'
|
|
40
|
+
|
|
41
|
+
<% } %> // Spring Cloud OpenFeign
|
|
42
|
+
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
|
|
43
|
+
<% if (features.hasKafka) { %>
|
|
44
|
+
// Kafka
|
|
45
|
+
implementation 'org.springframework.kafka:spring-kafka'
|
|
46
|
+
testImplementation 'org.springframework.kafka:spring-kafka-test'
|
|
47
|
+
|
|
48
|
+
<% } %><% if (dependencies.includes('web')) { %> implementation 'org.springframework.boot:spring-boot-starter-web'
|
|
49
|
+
<% } %><% if (dependencies.includes('data-jpa')) { %> implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
|
50
|
+
<% } %><% if (dependencies.includes('security')) { %> implementation 'org.springframework.boot:spring-boot-starter-security'
|
|
51
|
+
<% } %><% if (dependencies.includes('validation')) { %> implementation 'org.springframework.boot:spring-boot-starter-validation'
|
|
52
|
+
<% } %><% if (dependencies.includes('actuator')) { %> implementation 'org.springframework.boot:spring-boot-starter-aop'
|
|
53
|
+
<% } %><% if (features.includeDevtools) { %> developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
|
54
|
+
<% } %><% if (features.includeLombok) { %>
|
|
55
|
+
compileOnly 'org.projectlombok:lombok'
|
|
56
|
+
annotationProcessor 'org.projectlombok:lombok'
|
|
57
|
+
<% } %><% if (dependencies.includes('data-jpa')) { %>
|
|
58
|
+
runtimeOnly '<%= databaseDriver %>'
|
|
59
|
+
<% } %><% if (features.includeSwagger) { %>
|
|
60
|
+
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
|
|
61
|
+
<% } %>
|
|
62
|
+
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
|
63
|
+
<% if (dependencies.includes('security')) { %> testImplementation 'org.springframework.security:spring-security-test'
|
|
64
|
+
<% } %><% if (testing.includeTestcontainers && dependencies.includes('data-jpa')) { %> testImplementation 'org.testcontainers:testcontainers:1.19.3'
|
|
65
|
+
testImplementation 'org.testcontainers:<%= databaseTestcontainer %>:1.19.3'
|
|
66
|
+
<% } %>}
|
|
67
|
+
|
|
68
|
+
tasks.named('test') {
|
|
69
|
+
useJUnitPlatform()
|
|
70
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
rootProject.name = '<%= artifactId %>'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
server:
|
|
2
|
+
port: <%= serverPort %>
|
|
3
|
+
servlet:
|
|
4
|
+
context-path: /
|
|
5
|
+
|
|
6
|
+
springdoc:
|
|
7
|
+
swagger-ui:
|
|
8
|
+
path: /swagger-ui.html
|
|
9
|
+
enabled: true
|
|
10
|
+
api-docs:
|
|
11
|
+
path: /api-docs
|
|
12
|
+
|
|
13
|
+
management:
|
|
14
|
+
endpoint:
|
|
15
|
+
health:
|
|
16
|
+
probes:
|
|
17
|
+
enabled: true
|
|
18
|
+
show-details: always
|
|
19
|
+
endpoints:
|
|
20
|
+
web:
|
|
21
|
+
exposure:
|
|
22
|
+
include: "health"
|
|
23
|
+
|
|
24
|
+
spring:
|
|
25
|
+
threads:
|
|
26
|
+
virtual:
|
|
27
|
+
enabled: true
|
|
28
|
+
application:
|
|
29
|
+
name: <%= artifactId %>
|
|
30
|
+
profiles:
|
|
31
|
+
active: ${PROFILE:local}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<% if (dependencies.includes('data-jpa')) { %>spring:
|
|
2
|
+
datasource:
|
|
3
|
+
url: ${DB_URL:<%= databaseUrl %>}
|
|
4
|
+
username: ${DB_USERNAME:<%= databaseUsername %>}
|
|
5
|
+
password: ${DB_PASSWORD:<%= databasePassword %>}
|
|
6
|
+
driver-class-name: <%= databaseDriverClass %>
|
|
7
|
+
|
|
8
|
+
jpa:
|
|
9
|
+
hibernate:
|
|
10
|
+
ddl-auto: update
|
|
11
|
+
show-sql: false
|
|
12
|
+
properties:
|
|
13
|
+
hibernate:
|
|
14
|
+
format_sql: false
|
|
15
|
+
dialect: <%= hibernateDialect %>
|
|
16
|
+
|
|
17
|
+
logging:
|
|
18
|
+
level:
|
|
19
|
+
root: INFO
|
|
20
|
+
<%= packageName %>: DEBUG
|
|
21
|
+
<% } %>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
spring:
|
|
2
|
+
kafka:
|
|
3
|
+
bootstrap-servers:
|
|
4
|
+
- localhost:9092 # Lista de brokers Kafka
|
|
5
|
+
producer:
|
|
6
|
+
properties:
|
|
7
|
+
spring.json.add.type.headers: false
|
|
8
|
+
key-serializer: org.apache.kafka.common.serialization.StringSerializer
|
|
9
|
+
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
|
|
10
|
+
retries: 3
|
|
11
|
+
consumer:
|
|
12
|
+
group-id: <%= projectName %>-api-group
|
|
13
|
+
auto-offset-reset: earliest
|
|
14
|
+
enable-auto-commit: false
|
|
15
|
+
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
|
|
16
|
+
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
|
|
17
|
+
properties:
|
|
18
|
+
spring.json.trusted.packages: "*"
|
|
19
|
+
spring.json.use.type.headers: false
|
|
20
|
+
spring.json.value.default.type: <%= packageName %>.shared.infrastructure.eventEnvelope.EventEnvelope
|
|
21
|
+
listener:
|
|
22
|
+
ack-mode: manual
|
|
23
|
+
concurrency: 3
|
|
24
|
+
retry:
|
|
25
|
+
max-attempts: 2
|
|
26
|
+
backoff-delay: 1500
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<% if (dependencies.includes('data-jpa')) { %>spring:
|
|
2
|
+
datasource:
|
|
3
|
+
url: <%= databaseUrl %>
|
|
4
|
+
username: <%= databaseUsername %>
|
|
5
|
+
password: <%= databasePassword %>
|
|
6
|
+
driver-class-name: <%= databaseDriverClass %>
|
|
7
|
+
|
|
8
|
+
jpa:
|
|
9
|
+
hibernate:
|
|
10
|
+
ddl-auto: update
|
|
11
|
+
show-sql: true
|
|
12
|
+
properties:
|
|
13
|
+
hibernate:
|
|
14
|
+
format_sql: true
|
|
15
|
+
dialect: <%= hibernateDialect %>
|
|
16
|
+
|
|
17
|
+
logging:
|
|
18
|
+
level:
|
|
19
|
+
root: INFO
|
|
20
|
+
<%= packageName %>: DEBUG
|
|
21
|
+
<% } %>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
spring:
|
|
2
|
+
kafka:
|
|
3
|
+
bootstrap-servers:
|
|
4
|
+
- localhost:9092 # Lista de brokers Kafka
|
|
5
|
+
producer:
|
|
6
|
+
properties:
|
|
7
|
+
spring.json.add.type.headers: false
|
|
8
|
+
key-serializer: org.apache.kafka.common.serialization.StringSerializer
|
|
9
|
+
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
|
|
10
|
+
retries: 3
|
|
11
|
+
consumer:
|
|
12
|
+
group-id: <%= projectName %>-api-group
|
|
13
|
+
auto-offset-reset: earliest
|
|
14
|
+
enable-auto-commit: false
|
|
15
|
+
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
|
|
16
|
+
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
|
|
17
|
+
properties:
|
|
18
|
+
spring.json.trusted.packages: "*"
|
|
19
|
+
spring.json.use.type.headers: false
|
|
20
|
+
spring.json.value.default.type: <%= packageName %>.shared.infrastructure.eventEnvelope.EventEnvelope
|
|
21
|
+
listener:
|
|
22
|
+
ack-mode: manual
|
|
23
|
+
concurrency: 3
|
|
24
|
+
retry:
|
|
25
|
+
max-attempts: 2
|
|
26
|
+
backoff-delay: 1500
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<% if (dependencies.includes('data-jpa')) { %>spring:
|
|
2
|
+
datasource:
|
|
3
|
+
url: ${DB_URL}
|
|
4
|
+
username: ${DB_USERNAME}
|
|
5
|
+
password: ${DB_PASSWORD}
|
|
6
|
+
driver-class-name: <%= databaseDriverClass %>
|
|
7
|
+
|
|
8
|
+
jpa:
|
|
9
|
+
hibernate:
|
|
10
|
+
ddl-auto: validate
|
|
11
|
+
show-sql: false
|
|
12
|
+
properties:
|
|
13
|
+
hibernate:
|
|
14
|
+
format_sql: false
|
|
15
|
+
dialect: <%= hibernateDialect %>
|
|
16
|
+
|
|
17
|
+
logging:
|
|
18
|
+
level:
|
|
19
|
+
root: WARN
|
|
20
|
+
<%= packageName %>: INFO
|
|
21
|
+
<% } %>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
spring:
|
|
2
|
+
kafka:
|
|
3
|
+
bootstrap-servers:
|
|
4
|
+
- localhost:9092 # Lista de brokers Kafka
|
|
5
|
+
producer:
|
|
6
|
+
properties:
|
|
7
|
+
spring.json.add.type.headers: false
|
|
8
|
+
key-serializer: org.apache.kafka.common.serialization.StringSerializer
|
|
9
|
+
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
|
|
10
|
+
retries: 3
|
|
11
|
+
consumer:
|
|
12
|
+
group-id: <%= projectName %>-api-group
|
|
13
|
+
auto-offset-reset: earliest
|
|
14
|
+
enable-auto-commit: false
|
|
15
|
+
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
|
|
16
|
+
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
|
|
17
|
+
properties:
|
|
18
|
+
spring.json.trusted.packages: "*"
|
|
19
|
+
spring.json.use.type.headers: false
|
|
20
|
+
spring.json.value.default.type: <%= packageName %>.shared.infrastructure.eventEnvelope.EventEnvelope
|
|
21
|
+
listener:
|
|
22
|
+
ack-mode: manual
|
|
23
|
+
concurrency: 3
|
|
24
|
+
retry:
|
|
25
|
+
max-attempts: 2
|
|
26
|
+
backoff-delay: 1500
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# <%= projectName %>
|
|
2
|
+
|
|
3
|
+
<%= description %>
|
|
4
|
+
|
|
5
|
+
## Built with eva4j CLI
|
|
6
|
+
|
|
7
|
+
This project was generated using [eva4j](https://github.com/your-repo/eva4j), a CLI tool for generating Spring Boot projects with modular architecture.
|
|
8
|
+
|
|
9
|
+
## Technologies
|
|
10
|
+
|
|
11
|
+
- **Java**: <%= javaVersion %>
|
|
12
|
+
- **Spring Boot**: <%= springBootVersion %>
|
|
13
|
+
- **Build Tool**: Gradle <%= gradleVersion %>
|
|
14
|
+
<% if (dependencies.includes('data-jpa')) { %>- **Database**: <%= databaseType.toUpperCase() %>
|
|
15
|
+
<% } %><% if (dependencies.includes('web')) { %>- **REST API**: Spring Web
|
|
16
|
+
<% } %><% if (dependencies.includes('security')) { %>- **Security**: Spring Security
|
|
17
|
+
<% } %><% if (features.includeSwagger) { %>- **API Documentation**: Swagger/OpenAPI
|
|
18
|
+
<% } %>
|
|
19
|
+
|
|
20
|
+
## Project Structure
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
<%= artifactId %>/
|
|
24
|
+
├── src/
|
|
25
|
+
│ ├── main/
|
|
26
|
+
│ │ ├── java/
|
|
27
|
+
│ │ │ └── <%= packagePath %>/
|
|
28
|
+
│ │ │ ├── <%= applicationClassName %>.java
|
|
29
|
+
│ │ │ ├── common/ # Infrastructure layer
|
|
30
|
+
│ │ │ │ ├── config/
|
|
31
|
+
│ │ │ │ ├── exception/
|
|
32
|
+
│ │ │ │ └── util/
|
|
33
|
+
│ │ │ ├── shared/ # Shared domain layer (generated with first module)
|
|
34
|
+
│ │ │ └── [modules]/ # Domain modules (user, product, etc.)
|
|
35
|
+
│ │ └── resources/
|
|
36
|
+
│ │ └── application.yml
|
|
37
|
+
│ └── test/
|
|
38
|
+
├── build.gradle
|
|
39
|
+
└── docker-compose.yml
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Getting Started
|
|
43
|
+
|
|
44
|
+
### Prerequisites
|
|
45
|
+
|
|
46
|
+
- Java <%= javaVersion %> or higher
|
|
47
|
+
- Gradle <%= gradleVersion %> or use included wrapper
|
|
48
|
+
<% if (dependencies.includes('data-jpa') && databaseType !== 'h2') { %>- <%= databaseType.toUpperCase() %> database
|
|
49
|
+
<% } %>
|
|
50
|
+
|
|
51
|
+
### Running the Application
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Using Gradle wrapper
|
|
55
|
+
./gradlew bootRun
|
|
56
|
+
|
|
57
|
+
# Or build and run
|
|
58
|
+
./gradlew build
|
|
59
|
+
java -jar build/libs/<%= artifactId %>-<%= version %>.jar
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
<% if (features.includeDocker && dependencies.includes('data-jpa') && databaseType !== 'h2') { %>### Using Docker Compose
|
|
63
|
+
|
|
64
|
+
Start the database:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
docker-compose up -d
|
|
68
|
+
```
|
|
69
|
+
<% } %>
|
|
70
|
+
|
|
71
|
+
### Running Tests
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
./gradlew test
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
<% if (features.includeSwagger) { %>## API Documentation
|
|
78
|
+
|
|
79
|
+
Once the application is running, you can access the API documentation at:
|
|
80
|
+
|
|
81
|
+
- Swagger UI: http://localhost:<%= serverPort %>/swagger-ui.html
|
|
82
|
+
- OpenAPI JSON: http://localhost:<%= serverPort %>/api-docs
|
|
83
|
+
<% } %>
|
|
84
|
+
|
|
85
|
+
<% if (dependencies.includes('actuator')) { %>## Actuator Endpoints
|
|
86
|
+
|
|
87
|
+
Health check and metrics are available at:
|
|
88
|
+
|
|
89
|
+
- Health: http://localhost:<%= serverPort %>/actuator/health
|
|
90
|
+
- Metrics: http://localhost:<%= serverPort %>/actuator/metrics
|
|
91
|
+
<% } %>
|
|
92
|
+
|
|
93
|
+
## Adding Modules
|
|
94
|
+
|
|
95
|
+
To add a new domain module (e.g., user, product):
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
eva4j add module user
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This will generate:
|
|
102
|
+
- Controller layer (REST endpoints)
|
|
103
|
+
- Service layer (business logic)
|
|
104
|
+
- Repository layer (data access)
|
|
105
|
+
- Model/Entity (domain object)
|
|
106
|
+
- DTOs (data transfer objects)
|
|
107
|
+
- Mapper (entity ↔ DTO conversion)
|
|
108
|
+
- Tests
|
|
109
|
+
|
|
110
|
+
## Architecture
|
|
111
|
+
|
|
112
|
+
This project follows a **modular monolith** architecture with **package-by-feature** organization:
|
|
113
|
+
|
|
114
|
+
- **common**: Infrastructure and technical concerns (config, global exception handling)
|
|
115
|
+
- **shared**: Cross-cutting domain concerns (base entities, value objects, domain exceptions)
|
|
116
|
+
- **[module]**: Feature-based modules (user, product, order, etc.)
|
|
117
|
+
|
|
118
|
+
Each module is self-contained with its own controller, service, repository, model, and DTOs.
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
<%= license || 'MIT' %>
|
|
123
|
+
|
|
124
|
+
## Author
|
|
125
|
+
|
|
126
|
+
<%= author %>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Gradle
|
|
2
|
+
.gradle/
|
|
3
|
+
build/
|
|
4
|
+
!gradle/wrapper/gradle-wrapper.jar
|
|
5
|
+
!**/src/main/**/build/
|
|
6
|
+
!**/src/test/**/build/
|
|
7
|
+
|
|
8
|
+
# IDE
|
|
9
|
+
.idea/
|
|
10
|
+
.vscode/
|
|
11
|
+
*.iml
|
|
12
|
+
*.iws
|
|
13
|
+
*.ipr
|
|
14
|
+
out/
|
|
15
|
+
.DS_Store
|
|
16
|
+
|
|
17
|
+
# Compiled class files
|
|
18
|
+
*.class
|
|
19
|
+
|
|
20
|
+
# Log files
|
|
21
|
+
*.log
|
|
22
|
+
|
|
23
|
+
# Package Files
|
|
24
|
+
*.jar
|
|
25
|
+
*.war
|
|
26
|
+
*.nar
|
|
27
|
+
*.ear
|
|
28
|
+
*.zip
|
|
29
|
+
*.tar.gz
|
|
30
|
+
*.rar
|
|
31
|
+
|
|
32
|
+
# Virtual machine crash logs
|
|
33
|
+
hs_err_pid*
|
|
34
|
+
|
|
35
|
+
# Spring Boot
|
|
36
|
+
application-local.yml
|
|
37
|
+
application-local.properties
|
|
38
|
+
|
|
39
|
+
# Environment variables
|
|
40
|
+
.env
|
|
41
|
+
|
|
42
|
+
# Note: .eva4j.json is tracked to preserve project configuration across team members
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package <%= packageName %>.<%= moduleName %>.infrastructure.adapters.<%= portNameCamelCase %>;
|
|
2
|
+
|
|
3
|
+
import <%= packageName %>.<%= moduleName %>.application.ports.<%= portName %>;
|
|
4
|
+
import org.springframework.stereotype.Component;
|
|
5
|
+
|
|
6
|
+
@Component
|
|
7
|
+
public class <%= portName %>Adapter implements <%= portName %> {
|
|
8
|
+
|
|
9
|
+
private final <%= portName %>FeignClient feignClient;
|
|
10
|
+
|
|
11
|
+
public <%= portName %>Adapter(<%= portName %>FeignClient feignClient) {
|
|
12
|
+
this.feignClient = feignClient;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@Override
|
|
16
|
+
public Object findAll() {
|
|
17
|
+
return feignClient.findAll();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Override
|
|
21
|
+
public Object findById(Long id) {
|
|
22
|
+
return feignClient.findById(id);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@Override
|
|
26
|
+
public Object create(Object request) {
|
|
27
|
+
return feignClient.create(request);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Override
|
|
31
|
+
public Object update(Long id, Object request) {
|
|
32
|
+
return feignClient.update(id, request);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@Override
|
|
36
|
+
public void delete(Long id) {
|
|
37
|
+
feignClient.delete(id);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
package <%= packageName %>.<%= moduleName %>.infrastructure.adapters.<%= portNameCamelCase %>;
|
|
2
|
+
|
|
3
|
+
import feign.Logger;
|
|
4
|
+
import feign.Request;
|
|
5
|
+
import org.springframework.context.annotation.Bean;
|
|
6
|
+
|
|
7
|
+
import java.util.concurrent.TimeUnit;
|
|
8
|
+
|
|
9
|
+
public class <%= portName %>Config {
|
|
10
|
+
|
|
11
|
+
@Bean
|
|
12
|
+
public Logger.Level feignLoggerLevel() {
|
|
13
|
+
return Logger.Level.BASIC;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Bean
|
|
17
|
+
public Request.Options feignOptions() {
|
|
18
|
+
return new Request.Options(
|
|
19
|
+
15, TimeUnit.SECONDS, // connect timeout
|
|
20
|
+
15, TimeUnit.SECONDS, // read timeout
|
|
21
|
+
true
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package <%= packageName %>.<%= moduleName %>.infrastructure.adapters.<%= portNameCamelCase %>;
|
|
2
|
+
|
|
3
|
+
import org.springframework.cloud.openfeign.FeignClient;
|
|
4
|
+
import org.springframework.web.bind.annotation.*;
|
|
5
|
+
|
|
6
|
+
@FeignClient(name = "<%= feignClientName %>", url = "${<%= baseUrlProperty %>}", configuration = <%= portName %>Config.class)
|
|
7
|
+
public interface <%= portName %>FeignClient {
|
|
8
|
+
|
|
9
|
+
@GetMapping("/api/resources")
|
|
10
|
+
Object findAll();
|
|
11
|
+
|
|
12
|
+
@GetMapping("/api/resources/{id}")
|
|
13
|
+
Object findById(@PathVariable("id") Long id);
|
|
14
|
+
|
|
15
|
+
@PostMapping("/api/resources")
|
|
16
|
+
Object create(@RequestBody Object request);
|
|
17
|
+
|
|
18
|
+
@PutMapping("/api/resources/{id}")
|
|
19
|
+
Object update(@PathVariable("id") Long id, @RequestBody Object request);
|
|
20
|
+
|
|
21
|
+
@DeleteMapping("/api/resources/{id}")
|
|
22
|
+
void delete(@PathVariable("id") Long id);
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
package <%= packageName %>.<%= moduleName %>.application.ports;
|
|
2
|
+
|
|
3
|
+
public interface <%= portName %> {
|
|
4
|
+
|
|
5
|
+
Object findAll();
|
|
6
|
+
|
|
7
|
+
Object findById(Long id);
|
|
8
|
+
|
|
9
|
+
Object create(Object request);
|
|
10
|
+
|
|
11
|
+
Object update(Long id, Object request);
|
|
12
|
+
|
|
13
|
+
void delete(Long id);
|
|
14
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package <%= packageName %>.<%= moduleName %>.infrastructure.adapters.kafkaMessageBroker;
|
|
2
|
+
|
|
3
|
+
import <%= packageName %>.<%= moduleName %>.application.events.<%= eventClassName %>;
|
|
4
|
+
import <%= packageName %>.<%= moduleName %>.application.ports.MessageBroker;
|
|
5
|
+
import <%= packageName %>.shared.infrastructure.eventEnvelope.EventEnvelope;
|
|
6
|
+
import org.springframework.beans.factory.annotation.Value;
|
|
7
|
+
import org.springframework.kafka.core.KafkaTemplate;
|
|
8
|
+
import org.springframework.stereotype.Component;
|
|
9
|
+
import org.slf4j.MDC;
|
|
10
|
+
|
|
11
|
+
@Component
|
|
12
|
+
public class KafkaMessageBroker implements MessageBroker {
|
|
13
|
+
|
|
14
|
+
@Value("<%= topicSpringProperty %>")
|
|
15
|
+
private String <%= topicNameKebab.replace(/-/g, '') %>Topic;
|
|
16
|
+
|
|
17
|
+
private final KafkaTemplate<String, Object> kafkaTemplate;
|
|
18
|
+
|
|
19
|
+
public KafkaMessageBroker(KafkaTemplate<String, Object> kafkaTemplate) {
|
|
20
|
+
this.kafkaTemplate = kafkaTemplate;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
public void publish<%= eventClassName %>(<%= eventClassName %> event) {
|
|
25
|
+
EventEnvelope<<%= eventClassName %>> envelope = EventEnvelope.of(
|
|
26
|
+
<%= topicNameKebab.replace(/-/g, '') %>Topic,
|
|
27
|
+
event,
|
|
28
|
+
MDC.get("correlationId")
|
|
29
|
+
);
|
|
30
|
+
kafkaTemplate.send(<%= topicNameKebab.replace(/-/g, '') %>Topic, envelope);
|
|
31
|
+
}
|
|
32
|
+
}
|