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 send the payloadType with the name of the message when the payload is a String and produce a 400 BadRequest #752

Closed
pcomp96 opened this issue May 13, 2024 · 16 comments · Fixed by #759
Labels
bug Something isn't working staged for release

Comments

@pcomp96
Copy link

pcomp96 commented May 13, 2024

Describe the bug

I'm using spring integration with some jms adapter, I created the specification on my listener like in the code example.
When i try to publish a message from the SpringWolf UI , the client send this request body:

{
   "payload":"\"string\"",
   "payloadType":"XDataMessagePayload",
   "headers":{
      "x1":"xValue",
      "x2":"xValue"
   }

The payloadType is filled with the attribute name = "XDataMessagePayload" and not with the attribute payloadType = String.class setted in the annoation.
This produce a 400 BadRequest and a pubilsh failed error in the UI.


Dependencies and versions used
springboot version 3.2.3
springwolf-ui version 1.2.0
springwolf-core version 1.2.0
springwolf-jms version 1.2.0


Code example

Note: If I omit the attribute name="XDataMessagePayload" and have multiple messages with the same payloadType (String.class), in the UI the labels all appear the same as the last processed message.. 👎🏻

    @AsyncListener(
            operation = @AsyncOperation(
                    channelName = "queue-x-to-y-data",
                    description = "X send the data to Y over this channel", 
                    payloadType = String.class,
                    message = @AsyncMessage(
                            name = "XDataMessagePayload",
                            messageId = "XDataMessage",
                            description = "Example payload message that X send to Y",
                            title = "X Data to Y Message"
                    ),
                    headers = @Headers(
                            schemaName = "XToYDataHeaders",
                            values = {
                                    @Header(name = "header1", value = "X1", description = "X1 value"),
                                    @Header(name = "header2", value = "X2", description = "X2 value")
                            }
                    )
            ))
    @JmsAsyncOperationBinding
    public IntegrationFlow xDataToYListener(....){
              //Flow logic
             }

    @AsyncListener(
            operation = @AsyncOperation(
                    channelName = "queue-z-to-y-data",
                    description = "Z send the data to Y over this channel", 
                    payloadType = String.class,
                    message = @AsyncMessage(
                            name = "ZDataMessagePayload",
                            messageId = "ZDataMessage",
                            description = "Example payload message that Z send to Y",
                            title = "Z Data to Y Message"
                    ),
                    headers = @Headers(
                            schemaName = "ZToYDataHeaders",
                            values = {
                                    @Header(name = "header1", value = "Z1", description = "Z1 value"),
                                    @Header(name = "header2", value = "Z2", description = "Z2 value")
                            }
                    )
            ))
    @JmsAsyncOperationBinding
    public IntegrationFlow zDataToYListener(....){
              //Flow logic
             }

Stack trace and error logs

On the chrome console side :

Publishing to /springwolf/jms/publish with messageBinding {} and headers {"x1":"2021-07-01T00:00:00Z","x2":"24324234234"}: {"payload":"\"string\"","payloadType":"XDataMessagePayload ","headers":{"x1":"xValue","x2":"xValue"},"bindings":{}}
 
        POST http://localhost:8080/springwolf/jms/publish?topic=queue-x-to-y-data 400 (Bad Request)

On the backend side with the debug log enabled

INFO 20528 --- [nio-8080-exec-4] i.g.s.c.c.PublishingPayloadCreator       : Specified payloadType XDataMessagePayload is not a registered springwolf schema. Known payloadTypes: [XToYDataHeaders,"ZToYDataHeaders",java.lang.String]
@pcomp96 pcomp96 added the bug Something isn't working label May 13, 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.

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!

@pcomp96
Copy link
Author

pcomp96 commented May 18, 2024

Thank you for the fix, when u think to publish the release 1.3.x @timonback ?

I need to implement springwolf in my project for the docs generation and for testing purpose. ☺️

@timonback
Copy link
Member

Hi @pcomp96 ,
The plan is to release at the end of each month, so in two weeks.
Until then, you can use/verify the current snapshot version.

@pcomp96
Copy link
Author

pcomp96 commented May 18, 2024

This morning i have tested the 1.3.0-SNAPSHOT version but the error still presented.
Maybe i wasn't clear when i explain my issue.

If i remove the name attribute from @asyncmessage annotation the UI use the payloadType String.class as name of the message and this cause UI issue for the labels and consider both messages as same.

 @AsyncListener(
            operation = @AsyncOperation(
                    channelName = "${queue.in.x-to-me-feedback}",
                    description = "X send the feedback to Me over this channel", // Optional
                    payloadType = String.class,
                    message = @AsyncMessage(
                            name= "XFeedbackMessagePayload",
                            messageId = "XFeedbackMessage",
                            description = "Example payload message that X send to me",
                            title = "X send feedback to Me -  Message"
                    ),
                    headers = @Headers(
                            schemaName = "XToMeFeedbackHeaders",
                            values = {
                                    @Header(name = "headerXFeedback1", value = "1", description = "..."),
                                    @Header(name = "headerXFeedback2", value = "2", description = "...")
                            }
                    )
            )
    )
    @JmsAsyncOperationBinding
public IntegrationFlow jmsListenerXFeedback(...)


@AsyncListener(
            operation = @AsyncOperation(
                    channelName = "${queue.in.x-to-me-data}",
                    description = "X send the data to Me over this channel", 
                    payloadType = String.class,
                    message = @AsyncMessage(
                            name= "XDataMessagePayload",
                            messageId = "XDataMessage",
                            description = "Example payload message that X send to Me",
                            title = "X send data to Me - Message"
                    ),
                    headers = @Headers(
                            schemaName = "XToMeDataHeaders",
                            values = {
                                    @Header(name = "headerXData1", value = "1", description = ""),
                                    @Header(name = "headerXData2", value = "2", description = ""),
                            }
                    )
            )
    )
    @JmsAsyncOperationBinding
    @Bean
    public IntegrationFlow jmsListenerXData(...)

Without name attribute

You can see that i have the same labels on the operation but i have different message declaration on the annotation.

image

  • I have tried to remove the name attribute, I can send the text message from SpringWolfJmsController but send the incorrect message ( XDataToMe operation send a 'XFeedbackMessage' and not the correct message)

With name attribute

This error appear in Java console because send the name of the message and not the payload type...

Specified payloadType XDataMessagePayload is not a registered springwolf schema. Known payloadTypes

@timonback
Copy link
Member

Thanks for the update.

Can you share (parts of) the payload? Is it a string in both cases, but you want to have a different documentation for each one of them?

You might be looking for AsyncApiPayload annotation, see https://www.springwolf.dev/docs/configuration/documenting-messages/#primitive-final-and-external-classes
So that you have class XDataMessagePayload(){
@AsyncApiPayload
private String payload;
}

(Havent tested it, there can be a bug in publishing)

As a safety mechanism, you can only publish classes that have been registered as a schema. So, XDataMessagePayload must be used either as part of the method signature or payloadType in the annotation.

@pcomp96
Copy link
Author

pcomp96 commented May 18, 2024

The @AsyncApiPayload annotation not solve the problem
(i tried it, and the labels issue was there)

I do not want declare n. envelope classes for my n. String Messages(with different docs), honestly speaking, in my opinion is a bad approach.

I want only specific the message description and unique messageid for
the @asyncmessage annotation.

I think that the UI might send the payloadType as a String type in this case and not with the name of the message

UI

The labels are the same and the messages payload and header that the operations sends are the same.

This is a problem on testing side because the headers in the string messages are different.

Question: UI not use the message-id to distinguish the different message?

@timonback
Copy link
Member

Thanks for clarifying, I am trying to summarize.

First issue: You want to use the message description and id, but that does not work when using plain string.
Second issue: The ui mixes multiple messages together.

Publishing is just to verify, but the ui shows already unexpected data.
Just to confirm you have 2 different listener, for two different channels, both with the string payload, however different message ids and descriptions?

Regardless, I will need to properly reproduce this, probably on Friday. You can help, by forking the repo, adapting the jms example https://github.com/springwolf/springwolf-core/blob/master/springwolf-examples/springwolf-jms-example/src/main/java/io/github/springwolf/examples/jms/consumers/ExampleConsumer.java and opening a draft PR (no need for passing tests, etc). I want to make sure that I fully understand your issue and we can resolve it the next release.

@pcomp96
Copy link
Author

pcomp96 commented May 18, 2024

First issue: You want to use the message description and id, but that does not work when using plain string.
Second issue: The ui mixes multiple messages together.

  1. For the first issue

precisely when i set the name attribute in the @asyncmessage and the payloadType in @AsyncLis/Pub annotations is setted to String.class,
the UI use this value (name attribute) to fill the field payloadType in the request for testing the channel.
(It's wrong because not exist a payloadType with this name).

  1. For the second issue instead,

When i set String.class as payloadType and not set the name attribute in @asyncmessage,
the UI show the same messages label for the messages that have different messageId and same payloadType.
(It's caused by the name duplicate because the schemaName now is the String.class and so mix the message)

Publishing is just to verify, but the ui shows already unexpected data.
Just to confirm you have 2 different listener, for two different channels, both with the string payload, however different message ids and descriptions?

I have 2 listener on 2 different channels,
They have a String payload with different messageId,name and description.

Regardless, I will need to properly reproduce this, probably on Friday. You can help, by forking the repo, adapting the jms example https://github.com/springwolf/springwolf-core/blob/master/springwolf-examples/springwolf-jms-example/src/main/java/io/github/springwolf/examples/jms/consumers/ExampleConsumer.java and opening a draft PR (no need for passing tests, etc). I want to make sure that I fully understand your issue and we can resolve it the next release.

I'm not able to make a PR this week because i'm really busy sorry , but i think that my example on the top is enough to reproduce the steps.
I paste a skeleton to test

 @AsyncListener(
            operation = @AsyncOperation(
                    channelName = "${queue.in.x-to-me-feedback}",
                    description = "X send the feedback to Me over this channel", // Optional
                    payloadType = String.class,
                    message = @AsyncMessage(
                            name= "XFeedbackMessagePayload",
                            messageId = "XFeedbackMessage",
                            description = "Example payload message that X send to me",
                            title = "X send FEEDBACK to Me -  Message"
                    ),
                    headers = @Headers(
                            schemaName = "XToMeFeedbackHeaders",
                            values = {
                                    @Header(name = "headerFeedbackXToMe1", value = "1", description = "..headerFeedback XToMe1 description.."),
                                    @Header(name = "headerFeedbackXToMe2", value = "2", description = "..headerFeedback XToMe2 description.."),
                            }
                    )
            )
    )
    @JmsAsyncOperationBinding
    @Bean
    public IntegrationFlow xSendFeedbackListenerFlow(!NoPayloadHere){
//Flow logic
}


    @AsyncListener(
            operation = @AsyncOperation(
                    channelName = "${queue.in.x-to-me-data}",
                    description = "X send the data to Me over this channel", // Optional
                    payloadType = String.class,
                    message = @AsyncMessage(
                            name= "XDataMessagePayload",
                            messageId = "XDataMessage",
                            description = "Example payload message that X send to Me",
                            title = "X send DATA to Me - Message"
                    ),
                    headers = @Headers(
                            schemaName = "XToMeDataHeaders",
                            values = {
                                    @Header(name = "headerDataXToMe1", value = "1", description = "..headerData XToMe1 description.."),
                                    @Header(name = "headerDataXToMe2", value = "2", description = "..headerData XToMe2 description.."),
                            }
                    )
            )
    )
    @JmsAsyncOperationBinding
    @Bean
    public IntegrationFlow xSendDataListenerFlow(!NoPayloadHere){
//Flow logic
}

timonback added a commit to timonback/springwolf-core that referenced this issue May 19, 2024
@timonback
Copy link
Member

Hi @pcomp96,
I used your code to reproduce it in #764

#762 (show both descriptions, fix publishing with custom AsyncMessage#name) and #763 (using the messageId field internally) should address it.

@pcomp96
Copy link
Author

pcomp96 commented May 21, 2024

Hi @pcomp96,
I used your code to reproduce it in #764

#762 (show both descriptions, fix publishing with custom AsyncMessage#name) and #763 (using the messageId field internally) should address it.

Nice! 💯 @timonback
How can i test it into my project?

When you merge it into the master branch?

@timonback
Copy link
Member

Probably Friday, just tuen on the notifucations on both PRs, then you will get a ping automatically

@timonback
Copy link
Member

@pcomp96 The PRs have been merged and are ready as SNAPSHOT

@pcomp96
Copy link
Author

pcomp96 commented May 24, 2024

Hi @timonback ,
I tested some minutes ago the new solution and it works! 🚀
I'm looking forward to introducing version 1.3.0 into my project to document it 😄

Thanks again for your effort! I hope I was helpful! It was a pleasure, see you next time 🙏🏻 ⏭️

@timonback
Copy link
Member

Thank you, great collaboration!

Can we feature your company as an user, see #342 ?

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

Successfully merging a pull request may close this issue.

2 participants