Skip to content

Commit

Permalink
[Refactor/YAPP-Github#523] Spring Modulith를 통해 이벤트 명세할 수 있도록 수정 (YAPP…
Browse files Browse the repository at this point in the history
…-Github#524)

* refactor: 클래스를 통해 이벤트 명세할 수 있도록 수정

* test: EventRule.kt 삭제

* refactor: testFixtures 삭제

* refactor: SPRING MODULITH 버전 변경

* feat: ApplicationModule 추가

* refactor: EventDetails에 DomainEvent 추가 및 publishedClasses 삭제

* refactor: CrmDocument 재작성

* feat: JMOLECULES 의존성 추가

* feat: AggregateRoot 조건 추가

* refactor: AggregateRoot 추가
  • Loading branch information
belljun3395 authored Jan 10, 2025
1 parent edd843e commit 47ea415
Show file tree
Hide file tree
Showing 24 changed files with 79 additions and 336 deletions.
5 changes: 4 additions & 1 deletion buildSrc/src/main/kotlin/DependencyVersion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ object DependencyVersion {
const val SPRING_DEPENDENCY_MANAGEMENT = "1.1.5"

/** springModulith */
const val SPRING_MODULITH = "1.3.0"
const val SPRING_MODULITH = "1.3.1"

/** jmolecules */
const val JMOLECULES = "0.24.1"

/** jwt */
const val JWT = "0.11.5"
Expand Down
1 change: 0 additions & 1 deletion domain/crm/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ dependencies {
implementation(project(":library:web"))
implementation(project(":library:email"))
implementation(project(":library:event"))
testImplementation(testFixtures(project(":library:event")))

/** jsoup - html parser */
implementation("org.jsoup:jsoup:1.15.3")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@org.springframework.modulith.ApplicationModule(
type = ApplicationModule.Type.OPEN
)
package com.few.crm.config;

import org.springframework.modulith.ApplicationModule;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package com.few.crm.email.domain

import com.few.crm.email.event.send.EmailSentEvent
import event.domain.DomainAbstractAggregateRoot
import org.jmolecules.ddd.annotation.AggregateRoot

@AggregateRoot
class SentEmail(
private val userExternalId: String,
private val emailBody: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ abstract class ScheduledEvent(
eventTime,
)

@EventDetails(publishedLocations = ["com.few.crm.support.schedule.TimeOutEventTaskManager"])
@EventDetails
class CancelScheduledEvent(
val targetEventId: String,
eventId: String = EventUtils.generateEventId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ abstract class EmailSendEvent(

@EventDetails(
outBox = false,
publishedLocations = [
"com.few.crm.email.domain.SentEmail",
"com.few.crm.email.event.send.handler.NotificationEmailSendTimeOutInvokeEventHandler",
],
)
class EmailSentEvent(
val userExternalId: String,
Expand All @@ -65,7 +61,7 @@ class EmailSentEvent(
timestamp = timestamp,
)

@EventDetails(outBox = false, publishedLocations = ["com.few.crm.email.relay.send.EmailSendEventMessageMapper"])
@EventDetails(outBox = false)
class EmailDeliveryEvent(
eventId: String,
eventType: String,
Expand All @@ -82,7 +78,7 @@ class EmailDeliveryEvent(
timestamp = timestamp,
)

@EventDetails(outBox = false, publishedLocations = ["com.few.crm.email.relay.send.EmailSendEventMessageMapper"])
@EventDetails(outBox = false)
class EmailOpenEvent(
eventId: String,
eventType: String,
Expand All @@ -99,7 +95,7 @@ class EmailOpenEvent(
timestamp = timestamp,
)

@EventDetails(outBox = false, publishedLocations = ["com.few.crm.email.relay.send.EmailSendEventMessageMapper"])
@EventDetails(outBox = false)
class EmailClickEvent(
eventId: String,
eventType: String,
Expand All @@ -116,7 +112,7 @@ class EmailClickEvent(
timestamp = timestamp,
)

@EventDetails(outBox = false, publishedLocations = ["com.few.crm.email.relay.send.EmailSendEventMessageMapper"])
@EventDetails(outBox = false)
class EmailDeliveryDelayEvent(
eventId: String,
eventType: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ import event.TimeOutEvent
import org.springframework.context.ApplicationEventPublisher
import java.time.LocalDateTime

@EventDetails(
publishedLocations = [
"com.few.crm.email.event.send.replayer.NotificationEmailSendTimeOutEventReplayer",
"com.few.crm.view.email.CrmEmailSendView",
],
)
@EventDetails
open class NotificationEmailSendTimeOutEvent(
val templateId: Long,
val userIds: List<Long>,
Expand Down Expand Up @@ -73,12 +68,7 @@ open class NotificationEmailSendTimeOutEvent(
)
}

@EventDetails(
publishedLocations = [
"com.few.crm.email.event.send.NotificationEmailSendTimeOutInvokeEvent",
"com.few.crm.email.relay.send.aws.ScheduledEventReverseRelay",
],
)
@EventDetails()
class NotificationEmailSendTimeOutInvokeEvent(
val templateId: Long,
val userIds: List<Long>,
Expand All @@ -93,7 +83,7 @@ class NotificationEmailSendTimeOutInvokeEvent(
eventTime,
)

@EventDetails(publishedLocations = ["com.few.crm.email.event.send.NotificationEmailSendTimeOutEvent"])
@EventDetails()
class AwsNotificationEmailSendTimeOutEvent(
templateId: Long,
userIds: List<Long>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ abstract class EmailTemplateTransactionAfterCompletionEvent(
eventTime = eventTime,
)

@EventDetails(publishedLocations = ["com.few.crm.email.domain.EmailTemplate"])
@EventDetails
class PostEmailTemplateEvent(
val templateId: Long,
eventId: String = EventUtils.generateEventId(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@org.springframework.modulith.ApplicationModule(
type = ApplicationModule.Type.OPEN
)
package com.few.crm.email;

import org.springframework.modulith.ApplicationModule;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@org.springframework.modulith.ApplicationModule(
type = ApplicationModule.Type.OPEN
)
package com.few.crm.support;

import org.springframework.modulith.ApplicationModule;
6 changes: 6 additions & 0 deletions domain/crm/src/main/kotlin/com/few/crm/user/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@org.springframework.modulith.ApplicationModule(
type = ApplicationModule.Type.OPEN
)
package com.few.crm.user;

import org.springframework.modulith.ApplicationModule;
6 changes: 6 additions & 0 deletions domain/crm/src/main/kotlin/com/few/crm/view/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@org.springframework.modulith.ApplicationModule(
type = ApplicationModule.Type.OPEN
)
package com.few.crm.view;

import org.springframework.modulith.ApplicationModule;
108 changes: 25 additions & 83 deletions domain/crm/src/test/kotlin/com/few/crm/document/CrmDocument.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.few.crm.document

import com.tngtech.archunit.base.DescribedPredicate
import com.tngtech.archunit.core.domain.JavaClass
import com.tngtech.archunit.core.domain.JavaModifier
import com.tngtech.archunit.core.importer.ClassFileImporter
import event.Event
import event.EventDetails
import io.qameta.allure.Allure
import io.qameta.allure.Epic
import io.qameta.allure.Feature
Expand All @@ -22,21 +20,24 @@ class CrmDocument {
@Nested
inner class DependencyDiagram {
@Story("CRM 모듈 의존성 다이어그램")
@Link("https://thetimetube.herokuapp.com/asciidoc/")
@Link("https://www.planttext.com/")
@Test
fun `create dependency diagram`() {
val modules = ApplicationModules.of("com.few.crm")
val modules =
ApplicationModules.of(
"com.few.crm",
DescribedPredicate.describe(
"ignore event classes",
JavaClass.Predicates.assignableTo(Event::class.java),
),
)
Documenter(modules)
.writeDocumentation()
.writeIndividualModulesAsPlantUml()

modules
.filterNot { it.name == "config" }
.forEach {
val adocFile = File("build/spring-modulith-docs/module-${it.name}.adoc")
val pumlFile = File("build/spring-modulith-docs/module-${it.name}.puml")
Allure.addAttachment("${it.name} Module Adoc", "text/plain", adocFile.readText())
Allure.addAttachment("${it.name} Module Puml", "text/plain", pumlFile.readText())
}
}
Expand All @@ -46,85 +47,26 @@ class CrmDocument {
inner class EventDocument {
@Story("CRM 이벤트 발행 문서")
@Link("https://thetimetube.herokuapp.com/asciidoc/")
@Link("https://www.planttext.com/")
@Test
fun `create event document`() {
val classes = ClassFileImporter().importPackages("com.few.crm")
val eventClasses =
classes
.stream()
.filter { it.isAssignableTo(Event::class.java) }
.filter { it.isAnonymousClass.not() }
.filter { it.isInnerClass.not() }
.filter { it.isLocalClass.not() }
.filter { it.modifiers.contains(JavaModifier.ABSTRACT).not() }
.toList()

val notQualifiedEventClasses = mutableListOf<JavaClass>()
val logBuilder = StringBuilder()

eventClasses.forEach { event ->
if (event.isAnnotatedWith(EventDetails::class.java)) {
val eventDetails = event.getAnnotationOfType(EventDetails::class.java)
val publishedLocations = eventDetails.publishedLocations
if (publishedLocations.isEmpty()) {
notQualifiedEventClasses.add(event)
} else {
publishedLocations
.filter { it != (event.packageName + "." + event.simpleName) }
.forEach { publishedLocation ->
event.directDependenciesToSelf
.find {
it.originClass.fullName == publishedLocation
}?.let {
logBuilder.appendLine("* ${it.originClass.fullName}")
} ?: run {
notQualifiedEventClasses.add(event)
}
}
}
} else {
notQualifiedEventClasses.add(event)
}
}

if (notQualifiedEventClasses.isNotEmpty()) {
logBuilder.appendLine("\n== Not Qualified Event Classes")
logBuilder.appendLine("_The following event classes are not annotated with @EventDetails:_")
notQualifiedEventClasses.forEach {
logBuilder.appendLine("* ${it.fullName}")
}
throw IllegalStateException(logBuilder.toString())
}

val outputFile = File("build/event-docs/event-published-document.adoc")
if (outputFile.exists()) {
outputFile.delete()
}
outputFile.parentFile.mkdirs()
val adocContent = StringBuilder()

adocContent.appendLine("[%autowidth.stretch, cols=\"h,a\"]")
adocContent.appendLine("|===")
adocContent.appendLine("|Event Class | Published Locations")

eventClasses.forEach { event ->
val eventDetails = event.getAnnotationOfType(EventDetails::class.java)
val publishedLocations = eventDetails.publishedLocations

adocContent.appendLine("|`${event.simpleName}`")
adocContent.appendLine("|")
adocContent.appendLine(
publishedLocations.joinToString("\n") { "* `$it`" },
val modules =
ApplicationModules.of(
"com.few.crm",
)
Documenter(modules)
.writeModuleCanvases(
Documenter.CanvasOptions
.defaults()
.revealInternals()
.revealEmptyLines(),
)
}

adocContent.appendLine("|===")

outputFile.writeText(adocContent.toString())

Allure.addAttachment("Event Document", "text/plain", adocContent.toString())
println("Event document generated at: ${outputFile.absolutePath}")
modules
.filterNot { it.name == "config" }
.forEach {
val adocFile = File("build/spring-modulith-docs/module-${it.name}.adoc")
Allure.addAttachment("${it.name} Module Adoc", "text/plain", adocFile.readText())
}
}
}
}
6 changes: 1 addition & 5 deletions library/event/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ tasks.getByName("jar") {
enabled = true
}

plugins {
/** test fixtures */
id("java-test-fixtures")
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-json")
api("org.jmolecules.integrations:jmolecules-starter-ddd:${DependencyVersion.JMOLECULES}")
}
4 changes: 3 additions & 1 deletion library/event/src/main/kotlin/event/EventDetails.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package event

import org.jmolecules.event.annotation.DomainEvent

/**
* Event details
*
Expand All @@ -9,7 +11,7 @@ package event
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@DomainEvent
annotation class EventDetails(
val outBox: Boolean = false,
val publishedLocations: Array<String> = [],
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package event.domain

import event.domain.DomainEventPublishingMethod.Companion.NONE
import event.domain.util.AnnotationDetectionMethodCallback
import org.jmolecules.ddd.annotation.AggregateRoot
import org.springframework.context.ApplicationEventPublisher
import org.springframework.lang.Nullable
import org.springframework.util.ReflectionUtils
Expand All @@ -21,6 +22,10 @@ class DomainEventPublishingMethod(
throw IllegalArgumentException("Type must extend DomainAbstractAggregateRoot: $type")
}

if (!type.isAnnotationPresent(AggregateRoot::class.java)) {
throw IllegalArgumentException("Type must be annotated with @AggregateRoot: $type")
}

val result =
from(
type,
Expand Down
Loading

0 comments on commit 47ea415

Please sign in to comment.