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

Springwolf UI - Error parsing AsyncAPI message of channel io.eventuate.tram.spring.springwolf.events.Customer: Cannot read properties of undefined (reading '$ref') #1216

Open
cer opened this issue Mar 7, 2025 · 10 comments
Labels
bug Something isn't working

Comments

@cer
Copy link

cer commented Mar 7, 2025

My service generates this Async API doc: https://gist.github.com/cer/ca1f729dbbc40ee417616d9e3dcefd59

https://studio.asyncapi.com/ says that it is valid.

But Springwolf UI displays the error

Error parsing AsyncAPI message of channel io.eventuate.tram.spring.springwolf.events.Customer: Cannot read properties of undefined (reading '$ref')

No operations are displayed.

I did notice, btw, that Springwolf UI requires channels to have an address property - otherwise the error message shows undefined as the channel name.

Suggestions?

Copy link

github-actions bot commented Mar 7, 2025

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.

@cer
Copy link
Author

cer commented Mar 7, 2025

It seems that the UI requires messages to have a "headers" property.
I've added that (see updated gist).
I'm now seeing these errors in the console:

Image

@cer
Copy link
Author

cer commented Mar 7, 2025

It seems that the UI requires messages to have a name and/or title property.

@timonback
Copy link
Member

Hi @cer,
Thank you for the report and versioned gists.

In the latest revision (2), springwolf-ui renders the messages and operations, only the binding is missing. You probably want to add one of binding annotations, see: https://www.springwolf.dev/docs/configuration/documenting-bindings/

Indeed, name, title and headers are mandatory fields in springwolf-ui at this point 1.
Did you generate the AsyncAPI using Springwolf (i.e. springwolf-kafka) or use springwolf-ui only 2?

@cer
Copy link
Author

cer commented Mar 7, 2025

@timonback Yes revision (2) worked. I will work on adding bindings.

The AsyncAPI doc is generated by an Eventuate-specific SpringWolf plugin - https://github.com/eventuate-platform/eventuate-tram-spring-wolf-support/

Thanks for the link to https://github.com/springwolf/springwolf-core/blob/master/springwolf-ui/src/app/models/message.model.ts - the challenge is that the UI is generating difficult to debug errors on AsyncAPI docs that are valid according to asyncapi validate

@cer
Copy link
Author

cer commented Mar 7, 2025

Here's a different doc - https://gist.github.com/cer/cba0099872915d8ec16fd89d0c7209d0
It uses request/reply.

SpringWolf UI seems require the reply channel to have an address property: https://gist.github.com/cer/cba0099872915d8ec16fd89d0c7209d0#file-request-reply-json-L29

AFAIK this contradicts the specification for operation reply objects

When address is specified, the address property of the channel referenced by this property MUST be either null or not defined.

Thoughts?

@timonback
Copy link
Member

timonback commented Mar 7, 2025

Hi @cer,
Great to see you building your custom plugins!

We started looking into how to validate the provided AsyncAPI files in springwolf-ui (#1219), so that better error messages are being displayed in the browser console as INFO. Currently we use a strict mode so that also additional properties that are no issue appear in the console.
We are about to merge a preview version as -SNAPSHOT so that you can continue testing. We will come back to improve it.


Regarding your second question of address in channels for request/reply semantics:
Stomp (WebSocket) uses the reply object:

"reply": {
"channel": {
"$ref": "#/channels/_app_topic_sendto-response-queue"
},
"messages": [
{
"$ref": "#/channels/_app_topic_sendto-response-queue/messages/io.github.springwolf.examples.stomp.dtos.ExamplePayloadDto"
}
]
}

We address your concern by writing the address always to the channel object and do not specify it as part of the reply object. Will that work for you too?

@cer
Copy link
Author

cer commented Mar 9, 2025

Regarding your second question of address in channels for request/reply semantics:
...
We address your concern by writing the address always to the channel object and do not specify it as part of the reply object. Will that work for you too?

I'm a bit confused about what you are asking.
In my scenario, the actual reply channel is specified by a header in the request message.

The spec says that this is specified using the reply.address.location property:

    "operations": {
        "io.eventuate.tram.spring.springwolf.commands.requestasyncresponse.CustomerCommandHandler.reserveCredit": {
            "action": "receive",
            ....
            "reply": {
                "address": {
                    "location": "$message.header#/command_reply_to"
                },
                "channel": {
                    "$ref": "#/channels/io.eventuate.tram.spring.springwolf.commands.requestasyncresponse.CustomerCommandHandler.reserveCredit-reply"
                },

Moreover, the specification for operation reply objects says:

When address is specified, the address property of the channel referenced by this property MUST be either null or not defined.

In other words, the reply channel's address property that the UI requires is not compliant:

    "channels": {
       ...
        "io.eventuate.tram.spring.springwolf.commands.requestasyncresponse.CustomerCommandHandler.reserveCredit-reply": {
            "address": "io.eventuate.tram.spring.springwolf.commands.requestasyncresponse.CustomerCommandHandler.reserveCredit-replyfoo",
            "messages": {

Please clarify.

PS. I'm a bit confused by the fact that asyncapi validate doesn't catch these errors.

@timonback
Copy link
Member

Hi @cer,
I plan to read the AsyncAPI spec in more detail on Friday, but want to give you a quick response now.

Springwolf currently covers request/reply semantics for fixed channel names. My personal impression is that the AsyncAPI spec allows to describe the same thing in multiple different APIs. For the Springwolf use-case, we could use the reply.address fields but have opted for leaving the reply.address empty and instead use the address in the channel.$ref.

In my scenario, the actual reply channel is specified by a header in the request message.

Since you use a runtime expression, the current Springwolf approach might not work (haven't read the spec in depth).

In other words, the reply channel's address property that the [Springwolf] UI requires is not compliant:

Before we did not encounter this case, however I agree that springwolf-ui cannot rely on every channel having an address.
This begs the questions, whether this reply-only channel without address should show up in springwolf-ui's navigation (when the actual address is unclear / dependent on the request). Possibly it is enough when it is being shown within the request channel.

PS. I'm a bit confused by the fact that asyncapi validate doesn't catch these errors.

The spec is specified using json-schema and some spectral rules. My personal impression is that it covers the structure of the document, but not everything (semantical). AsyncAPI studio/validate does show some errors in invalid specifications, but not all.


Is it fair to re-word the current bug description to the following or is there something else missing?

springwolf-ui is unable to render AsyncAPI compliant documents, which use a runtime expression in channel.location within reply operation objects.
This need is expressed by a custom plugin, see https://github.com/eventuate-platform/eventuate-tram-spring-wolf-support/

@cer
Copy link
Author

cer commented Mar 10, 2025

Is it fair to re-word the current bug description to the following or is there something else missing?

I think this is about right.

However, there is an issue I reported earlier about the UI requiring message name/title/headers: #1216 (comment)

As far as I can tell the spec says they are optional - perhaps the UI should not require them.

@timonback timonback added the bug Something isn't working label Mar 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants