ResponseEntity incorrectly maps values
I have two entities: Product and Variant. Each product has a set of Variant. To get a product, I have a controller endpoint:
http://localhost:8081/api/products/{id}
Hence to call a product, I'll have to call this endpoint:
Well, I have tried debugging the problem and even explicitly serializing the objects before I pass it to the ResponseEntity's body, none works. Images attached described my attempt on verifying whether the object passed to the .body
was changed:
Left picture: I explicitly serialize it and debugging the output to the console. You can see that the serialization process works correctly. Right picture: I only printed the first and last variant id of the product's variants. It resulted in the correct return of variant ids.
27 Replies
⌛
This post has been reserved for your question.
Hey @circle! Please useTIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here./close
or theClose Post
button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.
I could not share the codes here, but I'll give the repository where the problem can be reproduced:
https://github.com/vianneynara/kuenyawz-api/tree/develop/src/main/java/dev/realtards/kuenyawz
Interesting candidates (link to the classes):
- entities: Product, Variant
- mapper: Product
- DTOS that are sent back: Product, Variant
- Product Controller, Product Service
Severity: Receiving end received duplicate variant ids even though the rest of the fields are not duplicated
This is the generated mapper by Mapstruct. But as far as I understand my own code, the problem should not be during the logical process I wrote, it's not on the response pre-flight, but is on the flight/post-flight
The database for the product I showed:
Where on the case, I'm expecting:
- product id: 9636560366469120
- variant ids: {9636560370663424, 9636560370663425}
Got variants: {9636560370663424, 9636560370663424} instead
Correct output example: (variantId can have the same id as productId, id generations and identification is defnitely unrelated). I see that most outputs have the wrong variantId
Any help is much appreciated ^-^
No help available for command: is
Help is
No help available for command: is
Hi
The problem is in Swagger itself
open Developer tools network tab
and compare response body:
Postman:
And I removed
@JsonBackReference
from Variant.product
and @JsonManagedReference
from Product.variants
since you use dtos when get that data:
and:
And also fetch it eagerly.
I don't know what magic happens at http://localhost:8081/swagger-ui/index.html
in their Response body
output. But that's strange.
Maybe bug.
So, ResponseEntity
maps values correctly. Just Swagger
from Springdoc shows it incorrectly in UI even though response body in developer tools network tab is correct.It's really weird, I wouldn't just say it only happens in swagger, but the report came from the front end divison that uses my api 😂
let me check in postman
oh i never knew you can see the stuff there
Now you will
@JsonBackReference and @JsonManagedReference helped me at the ealy stage of development, for some reason I had circular backreference in the JSON and it causes stack overflow
I'm not sure what people usually do when declaring those relationships
Jumped between course episodes 😂 but I will review it again
Though I will admit, it didn't work that well. The problem disappears when I do:
Basically overriding the representation
Without those annotations if you would return entities instead of Dto represtations of it then you would get infinite references in entities serialisation to json. You would get infinite loop that would lead to stack overflow abd exception.
So don't serialise sheer entities, but dtos.
Yea you can escape the problem with to string and choose what to show. But better to map to dtos.
You are right, I even removed the overridden toString and it still works perfectly fine. Problem has probably resolved without my knowledge after switching to DTOs
If you are finished with your post, please close it.
If you are not, please ignore this message.
Note that you will not be able to send further messages here after this post have been closed but you will be able to create new posts.
Not sure when to use LAZY and EAGER yet, but as far as I know EAGER mean the beans will be loaded together (product -- variant loaded together)? And then what would be the implication of using LAZY on both entities?
I don't really know. Just also heard that beans with LAZY would be loaded when specifically requesting it. But I used it because chatgpt said that Hibernare might serialise Variants in products badly and might copy its previous object with older id when transaction is loaded lazily. So I switched to eager. But I don't think this is the solution.Just more strict rule for Hibernate to load all dependant entities at the same transaction.
When I debugged like you then in service method ProductDto is with correct variant ids for both loading Variants eagerly or lazily.
The problem is in front-end. For unknown reason Swagger shows variant ids wrong. But in response body numbers are correct.
I reported it to Springdoc issues on github.
Hah okay
Yeah and his front end, I also saw the network response. It's right, I'lll have to check with them
Thanks, I was planning to do so
If you are finished with your post, please close it.
If you are not, please ignore this message.
Note that you will not be able to send further messages here after this post have been closed but you will be able to create new posts.
Thank you so much!
Problem has been resolved, but is crazy.
If you are finished with your post, please close it.
If you are not, please ignore this message.
Note that you will not be able to send further messages here after this post have been closed but you will be able to create new posts.
Post Closed
This post has been closed by <@389034898666553344>.