diff --git a/_examples/axon-avro-holi-bank-example/pom.xml b/_examples/axon-avro-holi-bank-example/pom.xml
index 8acd453..d05fb07 100644
--- a/_examples/axon-avro-holi-bank-example/pom.xml
+++ b/_examples/axon-avro-holi-bank-example/pom.xml
@@ -27,6 +27,13 @@
import
pom
+
+ org.jmolecules
+ jmolecules-bom
+ 2023.1.2
+ import
+ pom
+
@@ -73,6 +80,21 @@
jakarta.annotation-api
+
+ org.jmolecules
+ kmolecules-ddd
+
+
+
+ org.jmolecules
+ jmolecules-cqrs-architecture
+
+
+
+ org.jmolecules
+ jmolecules-events
+
+
org.mockito.kotlin
@@ -110,7 +132,9 @@
io.toolisticon.kotlin.avro.maven
avro-kotlin-maven-plugin
${avro-kotlin.version}
-
+
+ NONE
+
generate-schema
diff --git a/_examples/axon-avro-holi-bank-example/src/main/kotlin/AxonAvroExampleApplication.kt b/_examples/axon-avro-holi-bank-example/src/main/kotlin/AxonAvroExampleApplication.kt
index 69199ce..376496e 100644
--- a/_examples/axon-avro-holi-bank-example/src/main/kotlin/AxonAvroExampleApplication.kt
+++ b/_examples/axon-avro-holi-bank-example/src/main/kotlin/AxonAvroExampleApplication.kt
@@ -12,9 +12,12 @@ import org.axonframework.queryhandling.QueryGateway
import org.axonframework.serialization.Serializer
import org.axonframework.serialization.json.JacksonSerializer
import org.springframework.beans.factory.annotation.Qualifier
+import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.event.ApplicationStartedEvent
import org.springframework.boot.runApplication
+import org.springframework.context.ApplicationContext
+import org.springframework.context.ApplicationContextAware
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
@@ -55,10 +58,12 @@ class AxonAvroExampleApplication {
class ExampleRunner(
val commandGateway: CommandGateway,
val queryGateway: QueryGateway
- ) {
+ ) : ApplicationContextAware {
companion object : KLogging()
+ private lateinit var applicationContext: ApplicationContext
+
@EventListener
fun runExample(event: ApplicationStartedEvent) {
logger.info {
@@ -124,7 +129,7 @@ class AxonAvroExampleApplication {
Transactions for account $bankAccountId:
-${transactions.items.joinToString( separator = "\n")}
+${transactions.items.joinToString(separator = "\n")}
================================================================================
""".trimIndent()
@@ -138,6 +143,13 @@ ${transactions.items.joinToString( separator = "\n")}
===============================================================================
""".trimIndent()
}
+
+ SpringApplication.exit(applicationContext, { 0 })
}
+
+ override fun setApplicationContext(applicationContext: ApplicationContext) {
+ this.applicationContext = applicationContext
+ }
+
}
}
diff --git a/axon-avro-generation/pom.xml b/axon-avro-generation/pom.xml
index b1eb955..3acd112 100644
--- a/axon-avro-generation/pom.xml
+++ b/axon-avro-generation/pom.xml
@@ -15,6 +15,18 @@
${project.artifactId}
Axon Avro Generation - strategies and processors for avro-kotlin-generator.
+
+
+
+ org.jmolecules
+ jmolecules-bom
+ 2023.1.2
+ import
+ pom
+
+
+
+
io.toolisticon.kotlin.avro
@@ -45,6 +57,25 @@
kotlin-code-generation-test
test
+
+
+
+ org.jmolecules
+ kmolecules-ddd
+ test
+
+
+
+ org.jmolecules
+ jmolecules-cqrs-architecture
+ test
+
+
+
+ org.jmolecules
+ jmolecules-events
+ test
+
diff --git a/axon-avro-generation/src/main/kotlin/AxonAvroGeneration.kt b/axon-avro-generation/src/main/kotlin/AxonAvroGeneration.kt
index 383509a..cb3002d 100644
--- a/axon-avro-generation/src/main/kotlin/AxonAvroGeneration.kt
+++ b/axon-avro-generation/src/main/kotlin/AxonAvroGeneration.kt
@@ -2,5 +2,22 @@ package io.holixon.axon.avro.generation
object AxonAvroGeneration {
- // empty marker
+
+ object jmolecules {
+
+ val ddd = try {
+ Class.forName("org.jmolecules.ddd.annotation.AggregateRoot")
+ true
+ } catch (e: ClassNotFoundException) {
+ false
+ }
+
+ val cqrs = try {
+ Class.forName("org.jmolecules.ddd.annotation.AggregateRoot")
+ true
+ } catch (e: ClassNotFoundException) {
+ false
+ }
+ }
+
}
diff --git a/axon-avro-generation/src/main/kotlin/meta/RecordMetaDataType.kt b/axon-avro-generation/src/main/kotlin/meta/RecordMetaDataType.kt
index decfc7f..d6d65ab 100644
--- a/axon-avro-generation/src/main/kotlin/meta/RecordMetaDataType.kt
+++ b/axon-avro-generation/src/main/kotlin/meta/RecordMetaDataType.kt
@@ -11,6 +11,7 @@ enum class RecordMetaDataType {
Command,
Query,
QueryResult,
+ Undefined,
;
val decapitalizedName = name.replaceFirstChar { c -> c.lowercase(Locale.getDefault()) }
diff --git a/axon-avro-generation/src/main/kotlin/processor/AxonRevisionAnnotationProcessor.kt b/axon-avro-generation/src/main/kotlin/processor/AxonRevisionAnnotationProcessor.kt
index f76b2ab..7240f0a 100644
--- a/axon-avro-generation/src/main/kotlin/processor/AxonRevisionAnnotationProcessor.kt
+++ b/axon-avro-generation/src/main/kotlin/processor/AxonRevisionAnnotationProcessor.kt
@@ -2,7 +2,7 @@ package io.holixon.axon.avro.generation.processor
import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi
import io.holixon.axon.avro.generation.meta.RecordMetaData.Companion.recordMetaData
-import io.holixon.axon.avro.generation.support.RevisionAnnotation
+import io.holixon.axon.avro.generation.support.AxonFrameworkAnnotations.RevisionAnnotation
import io.toolisticon.kotlin.avro.generator.processor.KotlinDataClassFromRecordTypeProcessorBase
import io.toolisticon.kotlin.avro.generator.spi.SchemaDeclarationContext
import io.toolisticon.kotlin.avro.model.RecordType
diff --git a/axon-avro-generation/src/main/kotlin/processor/AxonTargetIdentifierAnnotationProcessor.kt b/axon-avro-generation/src/main/kotlin/processor/AxonTargetIdentifierAnnotationProcessor.kt
index f926f69..6bee4ea 100644
--- a/axon-avro-generation/src/main/kotlin/processor/AxonTargetIdentifierAnnotationProcessor.kt
+++ b/axon-avro-generation/src/main/kotlin/processor/AxonTargetIdentifierAnnotationProcessor.kt
@@ -3,7 +3,8 @@ package io.holixon.axon.avro.generation.processor
import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi
import io.holixon.axon.avro.generation.meta.FieldMetaData.Companion.fieldMetaData
import io.holixon.axon.avro.generation.meta.FieldMetaDataType
-import io.holixon.axon.avro.generation.support.TargetAggregateIdentifierAnnotation
+import io.holixon.axon.avro.generation.support.AxonFrameworkAnnotations.TargetAggregateIdentifierAnnotation
+import io.holixon.axon.avro.generation.support.JMoleculesAnnotationSupplier.AssociationAnnotation
import io.toolisticon.kotlin.avro.generator.processor.ConstructorPropertyFromRecordFieldProcessorBase
import io.toolisticon.kotlin.avro.generator.spi.SchemaDeclarationContext
import io.toolisticon.kotlin.avro.model.RecordField
@@ -13,14 +14,18 @@ import io.toolisticon.kotlin.generation.builder.KotlinConstructorPropertySpecBui
@OptIn(ExperimentalKotlinPoetApi::class)
class AxonTargetIdentifierAnnotationProcessor : ConstructorPropertyFromRecordFieldProcessorBase() {
- override fun invoke(context: SchemaDeclarationContext, input: RecordField, builder: KotlinConstructorPropertySpecBuilder): KotlinConstructorPropertySpecBuilder = builder.apply {
- requireNotNull(input)
+ override fun invoke(
+ context: SchemaDeclarationContext,
+ input: RecordField,
+ builder: KotlinConstructorPropertySpecBuilder
+ ): KotlinConstructorPropertySpecBuilder = builder.apply {
+
+ AssociationAnnotation().addIfEnabled(this)
+
addAnnotation(TargetAggregateIdentifierAnnotation)
}
override fun test(ctx: SchemaDeclarationContext, input: Any): Boolean {
return super.test(ctx, input) && input is RecordField && input.fieldMetaData()?.type == FieldMetaDataType.Association
}
-
-
}
diff --git a/axon-avro-generation/src/main/kotlin/processor/JMoleculesAnnotationRecordTypeProcessor.kt b/axon-avro-generation/src/main/kotlin/processor/JMoleculesAnnotationRecordTypeProcessor.kt
new file mode 100644
index 0000000..e5ed2a4
--- /dev/null
+++ b/axon-avro-generation/src/main/kotlin/processor/JMoleculesAnnotationRecordTypeProcessor.kt
@@ -0,0 +1,43 @@
+package io.holixon.axon.avro.generation.processor
+
+import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi
+import io.holixon.axon.avro.generation.meta.RecordMetaData.Companion.recordMetaData
+import io.holixon.axon.avro.generation.meta.RecordMetaDataType
+import io.holixon.axon.avro.generation.meta.RecordMetaDataType.Command
+import io.holixon.axon.avro.generation.meta.RecordMetaDataType.Event
+import io.holixon.axon.avro.generation.meta.RecordMetaDataType.Query
+import io.holixon.axon.avro.generation.meta.RecordMetaDataType.QueryResult
+import io.holixon.axon.avro.generation.meta.RecordMetaDataType.Undefined
+import io.holixon.axon.avro.generation.support.JMoleculesAnnotationSupplier.CommandAnnotation
+import io.holixon.axon.avro.generation.support.JMoleculesAnnotationSupplier.DomainEventAnnotation
+import io.toolisticon.kotlin.avro.generator.processor.KotlinDataClassFromRecordTypeProcessorBase
+import io.toolisticon.kotlin.avro.generator.spi.SchemaDeclarationContext
+import io.toolisticon.kotlin.avro.model.RecordType
+import io.toolisticon.kotlin.generation.builder.KotlinDataClassSpecBuilder
+
+@OptIn(ExperimentalKotlinPoetApi::class)
+class JMoleculesAnnotationRecordTypeProcessor : KotlinDataClassFromRecordTypeProcessorBase() {
+
+ private fun recordMetaDataType(input: Any): RecordMetaDataType = if (input is RecordType) {
+ input.recordMetaData()?.type ?: Undefined
+ } else {
+ Undefined
+ }
+
+ override fun invoke(
+ context: SchemaDeclarationContext,
+ input: RecordType,
+ builder: KotlinDataClassSpecBuilder
+ ): KotlinDataClassSpecBuilder = builder.apply {
+ when (recordMetaDataType(input)) {
+ Event -> DomainEventAnnotation(input.canonicalName).addIfEnabled(this)
+ Command -> CommandAnnotation(input.canonicalName).addIfEnabled(this)
+ Query, QueryResult, Undefined -> {
+ }
+ }
+ }
+
+ override fun test(ctx: SchemaDeclarationContext, input: Any): Boolean {
+ return super.test(ctx, input) && Undefined != recordMetaDataType(input)
+ }
+}
diff --git a/axon-avro-generation/src/main/kotlin/support/_annotations.kt b/axon-avro-generation/src/main/kotlin/support/AxonFrameworkAnnotations.kt
similarity index 56%
rename from axon-avro-generation/src/main/kotlin/support/_annotations.kt
rename to axon-avro-generation/src/main/kotlin/support/AxonFrameworkAnnotations.kt
index 2633cb3..bad6414 100644
--- a/axon-avro-generation/src/main/kotlin/support/_annotations.kt
+++ b/axon-avro-generation/src/main/kotlin/support/AxonFrameworkAnnotations.kt
@@ -9,15 +9,17 @@ import org.axonframework.modelling.command.TargetAggregateIdentifier
import org.axonframework.serialization.Revision
@OptIn(ExperimentalKotlinPoetApi::class)
-data class RevisionAnnotation(
- val value: String,
-) : KotlinAnnotationSpecSupplier {
- override fun spec(): KotlinAnnotationSpec = buildAnnotation(Revision::class) {
- addMember(FORMAT_STRING, value)
+object AxonFrameworkAnnotations {
+
+ data class RevisionAnnotation(
+ val value: String,
+ ) : KotlinAnnotationSpecSupplier {
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(Revision::class) {
+ addMember(FORMAT_STRING, value)
+ }
}
-}
-@OptIn(ExperimentalKotlinPoetApi::class)
-data object TargetAggregateIdentifierAnnotation : KotlinAnnotationSpecSupplier {
- override fun spec(): KotlinAnnotationSpec = buildAnnotation(TargetAggregateIdentifier::class)
+ data object TargetAggregateIdentifierAnnotation : KotlinAnnotationSpecSupplier {
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(TargetAggregateIdentifier::class)
+ }
}
diff --git a/axon-avro-generation/src/main/kotlin/support/JMoleculesAnnotationSupplier.kt b/axon-avro-generation/src/main/kotlin/support/JMoleculesAnnotationSupplier.kt
new file mode 100644
index 0000000..13e3c77
--- /dev/null
+++ b/axon-avro-generation/src/main/kotlin/support/JMoleculesAnnotationSupplier.kt
@@ -0,0 +1,294 @@
+package io.holixon.axon.avro.generation.support
+
+import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi
+import io.holixon.axon.avro.generation.support.JMoleculesAnnotationSupplier.JMoleculesFeature.*
+import io.toolisticon.kotlin.avro.value.CanonicalName
+import io.toolisticon.kotlin.avro.value.CanonicalName.Companion.parse
+import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildAnnotation
+import io.toolisticon.kotlin.generation.KotlinCodeGeneration.className
+import io.toolisticon.kotlin.generation.builder.KotlinAnnotatableBuilder
+import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpec
+import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpecSupplier
+import kotlin.reflect.KClass
+
+@OptIn(ExperimentalKotlinPoetApi::class)
+sealed interface JMoleculesAnnotationSupplier : KotlinAnnotationSpecSupplier {
+ val feature: JMoleculesFeature
+
+ enum class JMoleculesFeature(val markerClass: CanonicalName) {
+
+ DDD(parse("org.jmolecules.ddd.annotation.AggregateRoot")),
+ CQRS(parse("org.jmolecules.architecture.cqrs.Command")),
+ EVENTS(parse("org.jmolecules.event.annotation.DomainEvent")),
+ ;
+
+ val enabled: Boolean = try {
+ Class.forName(markerClass.fqn)
+ true
+ } catch (e: ClassNotFoundException) {
+ false
+ }
+
+ fun className(type: String) = className(markerClass.namespace.value, type)
+ }
+
+
+ enum class PublisherType {
+
+ /**
+ * Expresses that the events published are intended for internal usage.
+ */
+ INTERNAL,
+
+ /**
+ * Expresses that the events published are intended for external usage.
+ */
+ EXTERNAL,
+
+ /**
+ * Expresses that the target audience of the events is undefined (default).
+ */
+ UNDEFINED;
+ }
+
+
+ fun addIfEnabled(builder: KotlinAnnotatableBuilder<*>) = if (feature.enabled) {
+ val annotation = spec()
+ builder.addAnnotation(annotation)
+ } else {
+ builder
+ }
+
+ fun className(type: String) = feature.className(type)
+
+ /**
+ * A domain event is a full-fledged part of the domain model, a representation of something that happened in the domain.
+ *
+ * Retention: RUNTIME
+ * Target: Type
+ */
+ data class DomainEventAnnotation(
+ private val eventName: CanonicalName,
+ ) : JMoleculesAnnotationSupplier {
+
+ override val feature: JMoleculesFeature = EVENTS
+
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("DomainEvent")) {
+ addStringMember("namespace", eventName.namespace.value)
+ addStringMember("name", eventName.name.value)
+ }
+ }
+
+ /**
+ * Identifies a command in the context of CQRS, i.e. a request to the system for the change of data.
+ *
+ * Retention: RUNTIME
+ * Target: TYPE
+ */
+ data class CommandAnnotation(
+ private val commandName: CanonicalName,
+ ) : JMoleculesAnnotationSupplier {
+ override val feature = CQRS
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("Command")) {
+ addStringMember("namespace", commandName.namespace.value)
+ addStringMember("name", commandName.name.value)
+ }
+ }
+
+ /**
+ * Identifies a domain event handler, i.e. logic to process a {@link DomainEvent}.
+ *
+ * Retention: RUNTIME
+ * Target: METHOD, ANNOTATION_TYPE
+ */
+ data class DomainEventHandlerAnnotation(
+ private val eventName: CanonicalName,
+ ) : JMoleculesAnnotationSupplier {
+
+ override val feature = EVENTS
+
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("DomainEventHandler")) {
+ addStringMember("namespace", eventName.namespace.value)
+ addStringMember("name", eventName.name.value)
+ }
+ }
+
+ /**
+ * Identifies a domain event publisher, i.e. logic to publish a {@link DomainEvent}.
+ *
+ * Retention: RUNTIME
+ * Target: METHOD, ANNOTATION_TYPE
+ */
+ data class DomainEventPublisherAnnotation(
+ private val eventName: CanonicalName,
+ private val publisher: PublisherType = PublisherType.UNDEFINED,
+ ) : JMoleculesAnnotationSupplier {
+ override val feature = EVENTS
+
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("DomainEventPublisher")) {
+ addStringMember("publishes", eventName.fqn)
+ addEnumMember("type", publisher)
+ }
+ }
+
+ /**
+ * Annotation to marks domain events as to be externalized, which means that they are intended to be published to
+ * infrastructure outside the application.
+ *
+ * Retention: RUNTIME
+ * Target: TYPE
+ */
+ data class ExternalizedAnnotation(
+ private val target: String,
+ ) : JMoleculesAnnotationSupplier {
+
+ override val feature = EVENTS
+
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("Externalized")) {
+ addStringMember("target", target)
+ }
+ }
+
+ /**
+ * Identifies a command dispatcher in the context of CQRS, i.e. logic to dispatch a {@link Command}.
+ *
+ * Retention: RUNTIME
+ * Target: METHOD, ANNOTATION_TYPE
+ */
+ data class CommandDispatcherAnnotation(
+ private val commandName: CanonicalName,
+ ) : JMoleculesAnnotationSupplier {
+
+ override val feature = CQRS
+
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(feature.className("CommandDispatcher")) {
+ /**
+ * Optional identification of the command dispatched by this dispatcher.
+ */
+ addStringMember("dispatches", commandName.fqn)
+ }
+ }
+
+ /**
+ * Identifies a command handler in the context of CQRS, i.e. logic to process a {@link Command}.
+ *
+ * Retention: RUNTIME
+ * Target: METHOD, ANNOTATION_TYPE, CONSTRUCTOR
+ */
+ data class CommandHandlerAnnotation(
+ private val commandName: CanonicalName,
+ ) : JMoleculesAnnotationSupplier {
+ override val feature = CQRS
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("CommandHandler")) {
+ addStringMember("namespace", commandName.namespace.value)
+ addStringMember("name", commandName.name.value)
+ }
+ }
+
+ /**
+ * Identifies a query model element in the context of CQRS.
+ *
+ * Retention: RUNTIME
+ * @Target(ElementType.TYPE)
+ */
+ data object QueryModelAnnotation : JMoleculesAnnotationSupplier {
+ override val feature = CQRS
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("QueryModel"))
+ }
+
+ /**
+ * Identifies an aggregate root, i.e. the root entity of an aggregate.
+ *
+ * Retention: RUNTIME
+ * Target: CLASS
+ */
+ data object AggregateRootAnnotation : JMoleculesAnnotationSupplier {
+ override val feature = DDD
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("AggregateRoot"))
+ }
+
+ /**
+ * An association to an [org.jmolecules.ddd.annotation.AggregateRoot].
+ *
+ * Retention: RUNTIME
+ * Target: ANNOTATION_CLASS, FIELD, PROPERTY, PROPERTY_GETTER
+ */
+ data class AssociationAnnotation(
+ private val aggregateType: KClass<*>? = null,
+ ) : JMoleculesAnnotationSupplier {
+ override val feature = DDD
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("Association")) {
+ aggregateType?.let {
+ this.addKClassMember("aggregateType", it)
+ }
+ }
+ }
+
+ /**
+ * Identifies an [Entity].
+ *
+ * Retention: RUNTIME
+ * Target: CLASS
+ */
+ data object EntityAnnotation : JMoleculesAnnotationSupplier {
+ override val feature = DDD
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("Entity"))
+ }
+
+ /**
+ * Identifies a [Factory].
+ *
+ * Retention: RUNTIME
+ * Target: CLASS
+ */
+ data object FactoryAnnotation : JMoleculesAnnotationSupplier {
+ override val feature = DDD
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("Factory"))
+ }
+
+ /**
+ * Declares a field (or a getter) of a class to constitute the identity of the corresponding class.
+ *
+ * Retention: RUNTIME
+ * Target: ANNOTATION_CLASS, FIELD, PROPERTY, PROPERTY_GETTER
+ */
+ data object IdentityAnnotation : JMoleculesAnnotationSupplier {
+ override val feature = DDD
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("Identity"))
+ }
+
+
+ /**
+ * Identifies a [Repository].
+ *
+ * Retention: RUNTIME
+ * Target: CLASS
+ */
+ data object RepositoryAnnotation : JMoleculesAnnotationSupplier {
+ override val feature = DDD
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("Repository"))
+ }
+
+ /**
+ * Identifies a domain [Service].
+ *
+ * Retention: RUNTIME
+ * Target: CLASS
+ */
+ data object ServiceAnnotation : JMoleculesAnnotationSupplier {
+ override val feature = DDD
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("Service"))
+ }
+
+ /**
+ * Identifies a value object. Domain concepts that are modeled as value objects have no conceptual identity or
+ * lifecycle. Implementations should be immutable, operations on it are side effect free.
+ *
+ * Retention: RUNTIME
+ * Target: CLASS
+ */
+ data object ValueObjectAnnotation : JMoleculesAnnotationSupplier {
+ override val feature = DDD
+ override fun spec(): KotlinAnnotationSpec = buildAnnotation(className("ValueObject"))
+ }
+}
diff --git a/axon-avro-generation/src/main/resources/META-INF/services/io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationSpi b/axon-avro-generation/src/main/resources/META-INF/services/io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationSpi
index 3eb76ca..8ac7435 100644
--- a/axon-avro-generation/src/main/resources/META-INF/services/io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationSpi
+++ b/axon-avro-generation/src/main/resources/META-INF/services/io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationSpi
@@ -15,6 +15,8 @@ io.holixon.axon.avro.generation.strategy.AxonQueryProtocolInterfaceStrategy
io.holixon.axon.avro.generation.processor.AxonRevisionAnnotationProcessor
io.holixon.axon.avro.generation.processor.AxonTargetIdentifierAnnotationProcessor
+io.holixon.axon.avro.generation.processor.JMoleculesAnnotationRecordTypeProcessor
+
################################################################################
# logical types
################################################################################