Closed smallcar88 closed 2 years ago
@mhaack any ideas?
During the development, we have to extend the CIF component FeaturedCategoryList and modify the GraphQL query to retrieve the products from the selected category.
Do I understand your extension sample correct, you what the category to return all products with the attributes you specify. For that I suggest to build your own retriever. The FeaturedCategoryList
is build to query multiple categories with focus on category.
But the code from your example still looks ok to me. Can you enable query log (via debug logger for CIF GraphQL client) and posts the executed query.
Does the query work if used in a GraphQL tool? Can you share a sample GraphQL result?
During the development, we have to extend the CIF component FeaturedCategoryList and modify the GraphQL query to retrieve the products from the selected category.
Do I understand your extension sample correct, you what the category to return all products with the attributes you specify. For that I suggest to build your own retriever. The
FeaturedCategoryList
is build to query multiple categories with focus on category.But the code from your example still looks ok to me. Can you enable query log (via debug logger for CIF GraphQL client) and posts the executed query.
Does the query work if used in a GraphQL tool? Can you share a sample GraphQL result?
That is correct. We want to customize a component that when the user selects a category from Magento, it will load 10 latest products through GraphQL. We have a local forward proxy (built by npm package local-cors-proxy
) to print out the underlying GraphQL query during page loads. Then we test the query through GraphiQL tool and it executed successfully with an expected result.
Query
{
categoryList(filters: {category_uid: {in: ["NTY3"]}}) {
uid
name
url_key
url_path
position
image
products {
items {
__typename
name
sku
image {
url
}
min_club_point_custom_: min_club_point
price_range {
minimum_price {
discount {
amount_off
percent_off
}
final_price {
value
currency
}
regular_price {
value
currency
}
}
maximum_price {
discount {
amount_off
percent_off
}
final_price {
value
currency
}
regular_price {
value
currency
}
}
}
}
}
}
}
Response from GraphiQL
{
"data": {
"categoryList": [
{
"uid": "NTY3",
"name": "1 - 200 ClubPoint",
"url_key": "1-200-clubpoints",
"url_path": "rewards/1-200-clubpoints",
"position": 1,
"image": null,
"products": {
"items": [
{
"__typename": "VirtualProduct",
"name": "Gemini Body Measure Weight",
"sku": "CR-52085",
"image": {
"url": "https://shopping-t0.theclub.com.hk/media/catalog/product/cache/325fd8d4f7eaef1af70e0a1582ef0e80/g/w/gws2vrere.jpg"
},
"min_club_point_custom_": 100, // this is `Float` datatype, but throw an exception when parsing this value
"price_range": {
"minimum_price": {
"discount": {
"amount_off": 0,
"percent_off": 0
},
"final_price": {
"value": 180,
"currency": "HKD"
},
"regular_price": {
"value": 180,
"currency": "HKD"
}
},
"maximum_price": {
"discount": {
"amount_off": 0,
"percent_off": 0
},
"final_price": {
"value": 180,
"currency": "HKD"
},
"regular_price": {
"value": 180,
"currency": "HKD"
}
}
}
}
]
}
}
]
}
}
tldr; do not try to return objects from the GQL client by any public method that is part of a components JSON schema (served by Apache Sling Models Exporter using Jackson). The object tree may contain Google GSON specific instances that Jackson cannot serialise (as is).
If I read the stacktrace correct this is not related to the parsing of the GQL response but actually exposing the pages as model by the Sling Model Exporter to a SPA:
07.09.2021 09:43:25.758 *ERROR* [127.0.0.1 [1630979004078] GET /content/theclub-spa-react/spa.model.json HTTP/1.1] org.apache.sling.models.impl.ExportServlet.com.theclub.spa.react.core.models.impl.CustomPageImpl Could not perform export with jackson requested by model.
From the trace it seems that you added methods to your component interface that return the objects from the GQL client, which are then picked up by jackson when exporting for the .model.json
request.
com.theclub.spa.react.core.models.impl.CustomPageImpl[":children"]
->java.util.LinkedHashMap["/content/theclub-spa-react/spa/en-mobile"]
[...]
->com.theclub.spa.react.core.models.impl.TierBannerProductListImpl["categories"]
->java.util.ArrayList[0]
->com.adobe.cq.commerce.magento.graphql.CategoryTree["responseData"]
[...]
->java.util.HashMap["min_clubpoints"]
->com.google.gson.JsonPrimitive["asJsonObject"])
You see that Jackson tries to serialise an instance of JsonPrimitve. As jackson-databind is considering all bean-like named public methods it calls each of them on the instance including getAsJsonObject(). But as a JsonPrimitive is not a JsonObject, it fails with the exception you are seeing.
Please let us know if that helps to resolve your issue.
@Buuhuu Thank you for your response. If I understand your answer correctly, do you mean that we shouldn't let the Jackson model exporter to handle the serialization of the GraphQL response object as it may have unpredictable parsing result?
We end up implementing to reconstruct an array of simple data structure to pass to the Jackson Model Exporter and it worked and our purpose is served for now. Thank you for clarifying the issue again. Cheers.
Yes exactly.
This is one approach. Another would have been to use a custom Jackson serialiser for the field that returns the GQL response object and make it use GSON to serialise the object instead. This would have been a little less boilerplate I assume but either way is fine.
Closing as resolved.
User Story
Our company has a Magento commerce site that is up and running. We have added a custom membership point for a loyalty program. Afterward, we have decided to build another frontend site using AEM therefore we make use of CIF components to build the react frontend. During the development, we have to extend the CIF component
FeaturedCategoryList
and modify the GraphQL query to retrieve the products from the selected category. The retrieved products should include the custom GraphQL attribute mentioned above.Expected Behaviour
The customized attribute value (datatype
Number
) return from GraphQL should be parsed as a primitive number. Even a nullable attribute withnull
returned value is unable to parse successfully. The page JSON model can be rendered successfully.Actual Behaviour
The primitive value is processed by
asJsonObject
the Gson package used by the model exporter will throw an exception thatReproduce Scenario (including but not limited to)
I extend the GraphQL query using
categoriesRetriever.extendCategoryQueryWith()
and a customized attribute that is not an out-of-box Magento attribute.The return value is
0
which is a primitive number. However, the Gson package used by the model exporter will throw an exception.Steps to Reproduce
FeaturedCategoryList
categoriesRetriever.extendCategoryQueryWith()
APIPlatform and Version
AEM 6.5 Service Pack 8 aem-core-cif-components 2.0.0 com.adobe.commerce.cif.graphql-client 1.7.2 com.adobe.commerce.cif.magento-graphql 9.0.0.magento242ee
Sample Code that illustrates the problem
Logs taken while reproducing problem