In my previous articles, I have explained how to integrate AEM with Magento, in this article, I am going to explain how to read product information via GraphQL. If you are looking for Magento installation and integrate AEM with Magento then I would recommend you check below articles.

For easy understanding, I am taking a simple example which is reading product name, description and status via GraphQL. I am calling this component as Product Details component.
Here, I am using AEM Venia storefront which is a reference implementation to showcase B2C commerce journey, the good thing is it comes with predefined templates, themes, and components. We know that we are going to build a product details component, so we must place this component on the product details page. 
The reference implementation works on selectors, the product page contains product name in the URL and category page contains category id in the URL as selectors. To query specific product information first we need to have a filter and this filter is the product name, we can get this from the current page URL.
Generally, in traditional application’s we used to follow query strings to fetch data from the database dynamically. But in AEM instead of query string, we are using selectors.
Product details page selector :
selector-product
Category Id selector :
selector-cat
The below product details sling model gets the product name and description. explanation for every step is provided in the class as comments.

package com.aem.magento.integration.core.models;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.xss.XSSAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adobe.cq.commerce.core.components.client.MagentoGraphqlClient;
import com.adobe.cq.commerce.graphql.client.GraphqlResponse;
import com.adobe.cq.commerce.magento.graphql.ComplexTextValue;
import com.adobe.cq.commerce.magento.graphql.FilterTypeInput;
import com.adobe.cq.commerce.magento.graphql.Operations;
import com.adobe.cq.commerce.magento.graphql.ProductFilterInput;
import com.adobe.cq.commerce.magento.graphql.ProductInterface;
import com.adobe.cq.commerce.magento.graphql.ProductInterfaceQueryDefinition;
import com.adobe.cq.commerce.magento.graphql.ProductsQueryDefinition;
import com.adobe.cq.commerce.magento.graphql.Query;
import com.adobe.cq.commerce.magento.graphql.QueryQuery.ProductsArgumentsDefinition;
import com.adobe.cq.commerce.magento.graphql.StoreConfigQueryDefinition;
import com.adobe.cq.commerce.magento.graphql.gson.Error;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.designer.Style;
@Model(adaptables = SlingHttpServletRequest.class, adapters = ProductDetails.class, resourceType = ProductDetails.RESOURCE_TYPE)
public class ProductDetails {
	protected static final String RESOURCE_TYPE = "core/cif/components/commerce/productdetails";
	private static final Logger LOGGER = LoggerFactory.getLogger(ProductDetails.class);
	@Self
	@Optional
	private SlingHttpServletRequest request;
	@Inject
	@Optional
	private Resource resource;
	@Inject
	@Optional
	private Page currentPage;
	@ScriptVariable
	@Optional
	private Style currentStyle;
	@ScriptVariable
	@Optional
	private ValueMap properties;
	@Inject
	@Optional
	private XSSAPI xssApi;
	private ProductInterface product;
	private MagentoGraphqlClient magentoGraphqlClient;
	@PostConstruct
	private void initModel() {
		// Read product name from the current page
		String slug = readSelectorFromURL();
		LOGGER.error("slug" + slug);
		// Get MagentoGraphqlClient from the resource.
		magentoGraphqlClient = MagentoGraphqlClient.create(resource);
		LOGGER.error("slug" + resource.getPath());
		// Fetch product data
		if (magentoGraphqlClient != null) {
			product = fetchProduct(slug);
		}
	}
	public ProductInterfaceQueryDefinition generateProductQuery() {
		// Build product query, This query is going to fetch only two values which are name and description.
		return q -> q.name().description(d -> d.html());
	}
	private ProductInterface fetchProduct(String slug) {
		// The FilterTypeInput class have several methods, to identify product we need to pass
		// selector to the setEq method
		FilterTypeInput input = new FilterTypeInput().setEq(slug);
		// setUrlKey is something like page name in AEM, when you create a new product or category in Magento this will
		// automatically generate based on the provided name
		ProductFilterInput filter = new ProductFilterInput().setUrlKey(input);
		ProductsArgumentsDefinition searchArgs = s -> s.filter(filter);
		LOGGER.info("slug" + slug);
		LOGGER.info("slug" + searchArgs.toString());
		// The generateProductQuery method specifies what are all the fields we need to include in the
		// query results
		ProductsQueryDefinition queryArgs = q -> q.items(generateProductQuery());
		// The query method two parameters, search args and query arguments
		String queryString = Operations
				.query(query -> query.products(searchArgs, queryArgs).storeConfig(generateStoreConfigQuery()))
				.toString();
		// Send GraphQL request
		GraphqlResponse<Query, Error> response = magentoGraphqlClient.execute(queryString);
		// Get product list from response
		Query rootQuery = response.getData();
		List<ProductInterface> products = rootQuery.getProducts().getItems();
		// Return first product in list
		if (products.size() > 0) {
			return products.get(0);
		}
		return null;
	}
	private String safeDescription(ProductInterface product) {
		ComplexTextValue description = product.getDescription();
		if (description == null) {
			return null;
		}
		return xssApi.filterHTML(description.getHtml());
	}
	public String getName() {
		return product.getName();
	}
	public String getDescription() {
		return safeDescription(product);
	}
	private StoreConfigQueryDefinition generateStoreConfigQuery() {
		return q -> q.secureBaseMediaUrl();
	}
	private String readSelectorFromURL() {
		return request.getRequestPathInfo().getSelectorString();
	}
}

In product detail sightly template add below code, to render name and description,

<sly data-sly-use.product1="com.aem.magento.integration.core.models.ProductDetails"   >
 <p><h2> ${product1.name}</h2></p>
 <p> ${product1.description @ context='html'} </p>
</sly>

Output :
selector-output
In my next article, I will explain integrating AEM with Magento high level architecture.

By coderss

Leave a Reply

Your email address will not be published. Required fields are marked *