Skip to content

Commit

Permalink
change how the map is populated for channels found via AsyncApiCompon…
Browse files Browse the repository at this point in the history
…ent and for Channel annotations to handle the fact that not all of them will be named based on their class and that will only happen if they target a class instead of a function.
  • Loading branch information
Charles Bazeley committed Dec 17, 2024
1 parent 6e158c4 commit 7a428bd
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@ package org.openfolder.kotlinasyncapi.annotation

@Target(AnnotationTarget.CLASS)
@AsyncApiAnnotation
annotation class AsyncApiComponent(
val value: String = "",
)
annotation class AsyncApiComponent
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,24 @@ class AnnotationProvider(
listOfNotNull(
clazz.findAnnotation<Message>()?.let { clazz to it },
clazz.findAnnotation<Schema>()?.let { clazz to it },
clazz.findAnnotation<Channel>()?.let { clazz to it }
clazz.findAnnotation<Channel>()?.let { clazz to it },
clazz.findAnnotation<AsyncApiComponent>()?.let { clazz to it}
)
}
.mapNotNull { (clazz, annotation) ->
when (annotation) {
is Message -> messageProcessor.process(annotation, clazz)
is Schema -> schemaProcessor.process(annotation, clazz)
is Channel -> channelProcessor.process(annotation, clazz).also {
componentToChannelMapping[clazz.java.simpleName] =
annotation.value.takeIf { it.isNotEmpty() } ?: clazz.java.simpleName
if (clazz.annotations.any { it is Channel }) {
componentToChannelMapping[clazz.java.simpleName] =
annotation.value.takeIf { it.isNotEmpty() } ?: clazz.java.simpleName
}
}
is AsyncApiComponent -> asyncApiComponentProcessor.process(annotation, clazz).also {
componentToChannelMapping[clazz.java.simpleName] =
annotation.value.takeIf { it.isNotEmpty() } ?: clazz.java.simpleName
is AsyncApiComponent -> asyncApiComponentProcessor.process(annotation, clazz).also { processedComponents ->
processedComponents.channels?.forEach { (channelName, _) ->
componentToChannelMapping[channelName] = channelName
}
}
else -> null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ class AsyncApiComponentProcessor : AnnotationProcessor<AsyncApiComponent, KClass
return Components().apply {
channels {
context.functions.filter { it.hasAnnotation<Channel>() }.forEach { currentFunction ->
currentFunction.findAnnotation<Channel>()!!.toChannel()
var currentAnnotation = currentFunction.findAnnotation<Channel>()!!
currentAnnotation.toChannel()
.apply {
subscribe = subscribe ?: currentFunction.findAnnotation<Subscribe>()?.toOperation()
publish = publish ?: currentFunction.findAnnotation<Publish>()?.toOperation()
}
.also {
put(currentFunction.name, it)
put(currentAnnotation.value, it)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"channels" : {
"testSubscribe" : {
"some/{parameter}/channel" : {
"description" : "testDescription",
"servers" : [ "dev" ],
"subscribe" : {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.openfolder.kotlinasyncapi.springweb.controller

import org.junit.jupiter.api.Test
import org.openfolder.kotlinasyncapi.annotation.AsyncApiComponent
import org.openfolder.kotlinasyncapi.annotation.channel.Channel
import org.openfolder.kotlinasyncapi.annotation.channel.Message
import org.openfolder.kotlinasyncapi.annotation.channel.Publish
Expand Down Expand Up @@ -212,3 +213,52 @@ internal class AsyncApiControllerAnnotationIntegrationTest {
val optionalValue: Boolean?
)
}

@SpringBootTest
@AutoConfigureMockMvc
internal class AsyncApiComponentAnnotationControllerIntegrationTest {

@Autowired
lateinit var mockMvc: MockMvc

@Test
fun `should return AsyncApi document`() {
val expected = TestUtils.json("async_api_component_annotation_integration.json")

mockMvc.perform(get("/docs/asyncapi"))
.andExpect(MockMvcResultMatchers.status().is2xxSuccessful)
.andExpect(content().json(expected))
}

@SpringBootConfiguration
@EnableAutoConfiguration
@EnableAsyncApi
open class TestConfig {

@Bean
open fun asyncApiExtension() =
AsyncApiExtension.builder {
info {
title("testTitle")
version("testVersion")
}
}
}

@AsyncApiComponent
class TestChannel {

@Channel("my/channel")
@Publish(
description = "testDescription",
message = Message(TestMessage::class)
)
fun testOperation() {}
}

@Message
data class TestMessage(
val value: String,
val optionalValue: Boolean?
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"asyncapi": "2.4.0",
"info": {
"title": "testTitle",
"version": "testVersion"
},
"channels": {
"my/channel": {
"$ref": "#/components/channels/TestChannel"
}
},
"components": {
"schemas": {
"TestMessage": {
"required": [
"value"
],
"type": "object",
"properties": {
"value": {
"type": "string",
"exampleSetFlag": false,
"types": [
"string"
]
},
"optionalValue": {
"type": "boolean",
"exampleSetFlag": false,
"types": [
"boolean"
]
}
},
"exampleSetFlag": false
}
},
"channels": {
"my/channel": {
"publish": {
"description": "testDescription",
"message": {
"$ref": "#/components/messages/TestMessage"
}
}
}
},
"messages": {
"TestMessage": {
"payload": {
"$ref": "#/components/schemas/TestMessage"
},
"schemaFormat": "application/schema+json;version=draft-07"
}
}
}
}

0 comments on commit 7a428bd

Please sign in to comment.