Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duplicate AsyncAPI channel entry for public suspending function in Kotlin #705

Closed
ivo-leonov opened this issue Apr 16, 2024 · 10 comments
Closed
Labels
bug Something isn't working staged for release

Comments

@ivo-leonov
Copy link

Describe the bug
Annotating a public suspending function in Kotlin with @AsyncListener and/or @AsyncPublisher leads to two channel entries instead of one. Making the annotated method private or removing the suspend keyword resolves the issue. Both workarounds are suboptimal, as they require changing the code design.

Dependencies and versions used
springwolf-core and springwolf-ui version 1.1.0.

Code example
Kotlin class:

@Component
class AsyncConsumerProducer {
    @AsyncListener(
        operation =
        AsyncOperation(
            channelName = "INCOMING_REQUEST",
            description = "Inbound message.",
            payloadType = Input::class,
        ),
    )
    @AsyncPublisher(
        operation =
        AsyncOperation(
            channelName = "OUTBOUND_RESPONSE",
            description = "Outbound message.",
            payloadType = Output::class,
        ),
    )
    suspend fun consumeAndProduce(input: Input) = Output("result")
}

data class Input(val value: String)
data class Output(val value: String)

application.yaml:

springwolf:
  docket:
    base-package: com.example.springfoxissue
    info:
      title: "Title"
      version: v1
      description: AsyncAPI documentation
    servers:
      websockets:
        protocol: some.protocol
        host: localhost
  endpoint:
    actuator:
      enabled: false
  enabled: true

pom.xml:

        <dependency>
            <groupId>io.github.springwolf</groupId>
            <artifactId>springwolf-core</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.springwolf</groupId>
            <artifactId>springwolf-ui</artifactId>
            <version>1.1.0</version>
        </dependency>

Stack trace and error logs
image

@ivo-leonov ivo-leonov added the bug Something isn't working label Apr 16, 2024
Copy link

Welcome to Springwolf. Thanks a lot for reporting your first issue. Please check out our contributors guide and feel free to join us on discord.

timonback added a commit to timonback/springwolf-core that referenced this issue Apr 19, 2024
Co-authored-by: David Müller <david.mueller@codecentric.de>
@timonback
Copy link
Member

Hi @ivo-leonov

Thank you for the well described issue report!

We tried to re-produce the issue, but were not successful.
Attempt: #710

What are we missing?

timonback added a commit to timonback/springwolf-core that referenced this issue Apr 19, 2024
Co-authored-by: David Müller <david.mueller@codecentric.de>
@timonback timonback added the waiting for feedback Waiting for user feedback/response label Apr 21, 2024
@fcmdeveloper1
Copy link

Dear @timonback,
i tried for java and i have duplicate messages, although i used the @AsyncListener which should override the payload in the method itself.

but the topic name and the group name should still be taken from the @KafkaListener annotation, unless you will provide attribute for them in the @AsyncListener annotation

example:

@AsyncListener(
operation = @AsyncOperation(payloadType = LearningEvent.class, description = "description", channelName = "lms"
))
@KafkaListener(topics = "lms", groupId = "test")
public void receiveExamplePayload2(
@payload List<ConsumerRecord<String, LearningEvent>> records, Acknowledgment acknowledgment) {
log.info("Received new message in example-queue: {}", records.toString());
}

the generated asyncAPI has :

"channels": {
"lms": {
"messages": {
"com.asyncapi.kafka.dtos.LearningEvent": {
"$ref": "#/components/messages/com.asyncapi.kafka.dtos.LearningEvent"
},
"org.apache.kafka.clients.consumer.ConsumerRecord": {
"$ref": "#/components/messages/org.apache.kafka.clients.consumer.ConsumerRecord"
}
}
}
}

My Best Regards

@fcmdeveloper1
Copy link

Dear @timonback,
any update or work around for this

My Best Regards

@timonback
Copy link
Member

Hi @fcmdeveloper1,
Please open a separate issue for that as it is not related to the kotlin suspend function.

Have a look at https://www.springwolf.dev/docs/configuration/documenting-messages#unwrapping-the-payload and/or modify one of the springwolf-examples so that your issue is easily reproducible.

@timonback
Copy link
Member

timonback commented May 24, 2024

Hi @ivo-leonov

Thank you for the well described issue report!

We tried to re-produce the issue, but were not successful. Attempt: #710

What are we missing?

@ivo-leonov Any details?
Otherwise, I will go ahead and close the issue.

@github-actions github-actions bot removed the waiting for feedback Waiting for user feedback/response label May 24, 2024
@F43nd1r
Copy link

F43nd1r commented May 27, 2024

I created a reproducer here: https://github.com/F43nd1r/springwolf-issue-705-reproducer

Generated docs.yaml contains:

operations:
  my-topic_send_publishMessage:
    action: send
    channel:
      $ref: "#/channels/my-topic"
    title: my-topic_send
    description: Auto-generated description
    bindings: {}
    messages:
      - $ref: "#/channels/my-topic/messages/com.faendir.springwolfissue705reproducer.MyMessage"
  my-topic_send_publishMessage$suspendImpl:
    action: send
    channel:
      $ref: "#/channels/my-topic"
    title: my-topic_send
    description: Auto-generated description
    bindings: {}
    messages:
      - $ref: "#/channels/my-topic/messages/com.faendir.springwolfissue705reproducer.MyMessage"

The second is a synthetic method and should not be considered.

@timonback
Copy link
Member

Thank you @F43nd1r for sharing the used dependencies in your example.
After copying the configuration and producer from this issue, I was able to reproduce it.

It seems that the kotlin compiler is generating synthetic JVM methods.
To address it, I opened: #773

Copy link

The change is staged for release and will be part of the next release.

If you want to try and verify it in your application today,
use the latest 1.X.0-SNAPSHOT build as described in our README.md > Testing SNAPSHOT version

Thank you for the report/contribution!

Copy link

The change is available in the latest release. 🎉

Thank you for the report/contribution and making Springwolf better!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working staged for release
Projects
None yet
Development

No branches or pull requests

4 participants