Expand my Community achievements bar.

Modify ProductPicker

Avatar

Level 4

Hi,

I was going though the productpicker /libs/commerce/gui/components/common/productpicker and used it in one of my dialogues. By default it returns the base products and not the variants for each base product. Can i customize this to return variants as well ? If yes, how can I do it ?

9 Replies

Avatar

Level 10

I am checking with the product team on this question. 

Avatar

Level 4

Thanks Scott

Can i get the source code of the following file ? com.adobe.cq.commerce.pim.impl.contentfinder.ProductViewHandler 

It is placed within resources/install/0/cq-commerce-pim-5.11.30.jar but I am not sure where to look for this jar 

Avatar

Level 10

If you know the bundle number -- you can find the bundles here: 

C:\AEM61_3\crx-quickstart\launchpad\felix

Avatar

Level 10

We also have plans on providing more eCommerce content like this. It looks like we will be going an Ask the AEM Community Experts session on E Commerce in AUG too. 

Avatar

Level 4

Thanks for your reply Scott ! I am looking forward to that session in Aug. 

I did check crx-quickstart\launchpad\felix and found 475 bundles and realized it wouldn't be possible to find that particular jar.

I got the class file from https://repo.adobe.com/nexus/content/groups/public/com/adobe/cq/commerce/cq-commerce-pim/5.9.26/cq-commerce-pim-5.9.26.jar , decompiled it and found cq:commerceType value set as product which can be changed to variant in the ProductFilter

private static class ProductFilter implements GQL.Filter { ResourceResolver resolver; ProductFilter(ResourceResolver resolver) { this.resolver = resolver; } public boolean include(Row row) throws RepositoryException { String path = row.getPath(); Resource resource = this.resolver.getResource(path); if (resource == null) { return false; } ValueMap valueMap = (ValueMap)resource.adaptTo(ValueMap.class); return (valueMap.containsKey("cq:commerceType")) && (valueMap.get("cq:commerceType").equals("product")); } }

Would this be the correct way to achieve my requirement? Thanks again for your help on this.

Avatar

Level 10

Looks like you are on the right path - i would recommend that you test this on a DEV Sandbox CQ instance - so anything you do will not break anything important. 

Avatar

Level 4

Hey Scott,

I am getting the following error when I try to build my code

[ERROR] Exception Details:
[ERROR] Location:
[ERROR] com/day/cq/commons/servlets/AbstractPredicateServlet.<init>()V @1: return
[ERROR] Reason:
[ERROR] Error exists in the bytecode
[ERROR] Bytecode:
[ERROR] 0000000: 2ab1

[ERROR] -----------------------------------------------------
[ERROR] realm =    plugin>org.apache.felix:maven-scr-plugin:1.20.0
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/C:/Users/dhiagarwal/.m2/repository/org/apache/felix/maven-scr-plugin/1.20.0/maven-scr-plugin-1.20.0.jar
[ERROR] urls[1] = file:/C:/Users/dhiagarwal/.m2/repository/org/slf4j/slf4j-simple/1.5.11/slf4j-simple-1.5.11.jar
[ERROR] urls[2] = file:/C:/Users/dhiagarwal/.m2/repository/org/apache/maven/maven-archiver/2.2/maven-archiver-2.2.jar
[ERROR] urls[3] = file:/C:/Users/dhiagarwal/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar
[ERROR] urls[4] = file:/C:/Users/dhiagarwal/.m2/repository/org/codehaus/plexus/plexus-archiver/1.0-alpha-7/plexus-archiver-1.0-alpha-7.jar
[ERROR] urls[5] = file:/C:/Users/dhiagarwal/.m2/repository/org/apache/felix/org.apache.felix.scr.generator/1.12.0/org.apache.felix.scr.generator-1.12.0.jar
[ERROR] urls[6] = file:/C:/Users/dhiagarwal/.m2/repository/org/ow2/asm/asm-all/5.0.2/asm-all-5.0.2.jar
[ERROR] urls[7] = file:/C:/Users/dhiagarwal/.m2/repository/org/osgi/org.osgi.core/4.2.0/org.osgi.core-4.2.0.jar
[ERROR] urls[8] = file:/C:/Users/dhiagarwal/.m2/repository/org/osgi/org.osgi.compendium/4.2.0/org.osgi.compendium-4.2.0.jar
[ERROR] urls[9] = file:/C:/Users/dhiagarwal/.m2/repository/org/sonatype/plexus/plexus-build-api/0.0.7/plexus-build-api-0.0.7.jar
[ERROR] urls[10] = file:/C:/Users/dhiagarwal/.m2/repository/org/codehaus/plexus/plexus-utils/1.5.8/plexus-utils-1.5.8.jar
[ERROR] Number of foreign imports: 1
[ERROR] import: Entry[import  from realm ClassRealm[project>com.mec:meCommerce.core:0.0.1-SNAPSHOT, parent: ClassRealm[maven.api, parent: null]]]

I have tried jdk 1.7 as well as 1.8

Would I required an unobfuscated uber jar to have this work?

Added the code below.

package com.mec.core.servlets; import com.adobe.cq.commerce.api.Product; import com.adobe.granite.xss.XSSAPI; import com.day.cq.tagging.Tag; import com.day.cq.tagging.TagManager; import com.day.cq.wcm.core.contentfinder.Hit; import com.day.cq.wcm.core.contentfinder.ViewHandler; import com.day.cq.wcm.core.contentfinder.ViewQuery; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Value; import javax.jcr.query.Row; import javax.jcr.query.RowIterator; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Properties; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.apache.jackrabbit.commons.query.GQL; import org.apache.jackrabbit.commons.query.GQL.Filter; import org.apache.jackrabbit.commons.query.GQL.ParserCallback; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.request.RequestPathInfo; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ValueMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component @Service @Properties({ @Property(name = "service.description", value = { "Handles the display of the variants tab in the content finder" }), @Property(name = "sling.servlet.paths", value = { "/bin/wcm/contentfinder/variant/view" }) }) public class VariantViewHandler extends ViewHandler { private static Logger log = LoggerFactory.getLogger(VariantViewHandler.class); @Reference private XSSAPI xssAPI; private static final String DEFAULT_START_PATH = "/etc/commerce/products"; protected ViewQuery createQuery(SlingHttpServletRequest request, Session session, String queryString) throws RepositoryException { ParserCallback cb = new ParserCallback((TagManager) request.getResourceResolver().adaptTo(TagManager.class)); GQL.parse(queryString, session, cb); StringBuilder gql = cb.getQuery(); String path = cb.getStartPath(); if (path == null) { RequestPathInfo pathInfo = request.getRequestPathInfo(); String startPath = pathInfo.getSuffix() != null ? pathInfo.getSuffix() : "/etc/commerce/products"; path = "path:\"" + startPath + "\""; } if (gql.length() > 0) { gql.append(" "); } gql.append(path).append(" "); String limit = cb.getLimit(); if (limit == null) { limit = request.getParameter("limit"); if ((limit != null) && (!limit.equals(""))) { limit = "limit:" + limit; } else { limit = "limit:20"; } } gql.append(limit).append(" "); String order = cb.getOrder(); if (order == null) { order = "order:-jcr:lastModified"; } else if ((order.substring("order:-".length()).startsWith("jcr:content/")) || (order.substring("order:-\"".length()).startsWith("jcr:content/"))) { order = order.replaceFirst("jcr:content/", ""); } gql.append(order).append(" "); return new GQLViewQuery(request, gql.toString(), session, this.xssAPI.getRequestSpecificAPI(request)); } private static Hit createHit(Product product, String excerpt, XSSAPI xssAPI) throws RepositoryException { Hit hit = new Hit(); String path = product.getPath(); String name = path.substring(path.lastIndexOf("/") + 1); String title = product.getTitle(); if ((title == null) || (title.length() == 0)) { title = name; } hit.set("name", xssAPI.encodeForHTML(name)); hit.set("path", path); hit.set("thumbnail", xssAPI.getValidHref(product.getThumbnailUrl(48))); hit.set("title", xssAPI.encodeForHTML(title)); hit.set("sku", xssAPI.encodeForHTML(product.getSKU())); hit.set("excerpt", xssAPI.filterHTML(excerpt)); return hit; } protected void bindXssAPI(XSSAPI paramXSSAPI) { this.xssAPI = paramXSSAPI; } protected void unbindXssAPI(XSSAPI paramXSSAPI) { if (this.xssAPI == paramXSSAPI) { this.xssAPI = null; } } private static class ProductFilter implements GQL.Filter { ResourceResolver resolver; ProductFilter(ResourceResolver resolver) { this.resolver = resolver; } public boolean include(Row row) throws RepositoryException { String path = row.getPath(); Resource resource = this.resolver.getResource(path); if (resource == null) { return false; } ValueMap valueMap = (ValueMap) resource.adaptTo(ValueMap.class); return (valueMap.containsKey("cq:commerceType")) && (valueMap.get("cq:commerceType").equals("variant")); } } private static class ParserCallback implements GQL.ParserCallback { private StringBuilder query = new StringBuilder(); private String startPath = null; private String type = null; private String limit = null; private String order = null; private TagManager tagMgr; public ParserCallback(TagManager tagMgr) { this.tagMgr = tagMgr; } public void term(String property, String value, boolean optional) throws RepositoryException { if (property.equals("path")) { this.startPath = ("path:\"" + value + "\""); return; } if (property.equals("type")) { this.type = ("type:\"" + value + "\""); return; } if (property.equals("limit")) { this.limit = ("limit:\"" + value + "\""); return; } if (property.equals("order")) { this.order = ("order:\"" + value + "\""); return; } if (optional) { this.query.append("OR "); } if (property.equals("tag")) { if (this.tagMgr == null) { this.query.append("\"cq:tags\":\""); this.query.append(value).append("\" "); } else { Tag tag = this.tagMgr.resolve(value); if (tag != null) { this.query.append(tag.getGQLSearchExpression("cq:tags")); this.query.append(" "); } else { this.query.append("\"cq:tags\":\"______invalid______\" "); } } } else if (property.length() == 0) { this.query.append("\"").append(value).append("\""); } else { this.query.append("\"").append(property).append("\":"); this.query.append("\"").append(value).append("\" "); } } public StringBuilder getQuery() { return this.query; } public String getStartPath() { return this.startPath; } public String getType() { return this.type; } public String getLimit() { return this.limit; } public String getOrder() { return this.order; } } private static class GQLViewQuery implements ViewQuery { private final SlingHttpServletRequest request; private final String queryStr; private final Session session; private final XSSAPI xssAPI; public GQLViewQuery(SlingHttpServletRequest request, String queryStr, Session session, XSSAPI xssAPI) { this.request = request; this.queryStr = queryStr; this.session = session; this.xssAPI = xssAPI; } public Collection<Hit> execute() { List<Hit> hits = new ArrayList(); ResourceResolver resolver = this.request.getResourceResolver(); VariantViewHandler.log.debug("executing GQL query: " + this.queryStr); RowIterator rows = GQL.execute(this.queryStr, this.session, null, new VariantViewHandler.ProductFilter(resolver)); while (rows.hasNext()) { Row row = rows.nextRow(); try { Product product = (Product) resolver.getResource(row.getPath()).adaptTo(Product.class); String excerpt = ""; try { excerpt = row.getValue("rep:excerpt()").getString(); } catch (Exception e) { } hits.add(VariantViewHandler.createHit(product, excerpt, this.xssAPI)); } catch (RepositoryException re) { VariantViewHandler.log.error("A repository error occurred", re); } } return hits; } } }

Avatar

Administrator

Hi 

Reply for the internal team :-

    Returning other types than ‘product' is not supported by the product picker ootb.
    To achieve your goal you could maybe:
    •    Override /libs/commerce/gui/components/common/productpicker/clientlibs/productpicker.js in /apps and introduce a custom type (type=productorvariant)
    •    Create a custom view handler (e.g. CustomProductViewHandler), similar to com.adobe.cq.commerce.pim.impl.contentfinder.ProductViewHandler, that would return product or variant, registered to the path     /bin/wcm/contentfinder/productorvariant/view

I hope this would help you.

Thanks and Regards

Kautuk Sahni



Kautuk Sahni

Avatar

Level 4

Hi Kautuk,

 

Thanks for your reply.I have done the exact same thing as mentioned in my previous reply. however when i try to build my bundle which has the custom ViewHandler I get below error. Can you help me out here ?

[ERROR] Exception Details:
[ERROR] Location:
[ERROR] com/day/cq/commons/servlets/AbstractPredicateServlet.<init>()V @1: return
[ERROR] Reason:
[ERROR] Error exists in the bytecode
[ERROR] Bytecode:
[ERROR] 0000000: 2ab1

[ERROR] -----------------------------------------------------
[ERROR] realm =    plugin>org.apache.felix:maven-scr-plugin:1.20.0
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/C:/Users/dhiagarwal/.m2/repository/org/apache/felix/maven-scr-plugin/1.20.0/maven-scr-plugin-1.20.0.jar
[ERROR] urls[1] = file:/C:/Users/dhiagarwal/.m2/repository/org/slf4j/slf4j-simple/1.5.11/slf4j-simple-1.5.11.jar
[ERROR] urls[2] = file:/C:/Users/dhiagarwal/.m2/repository/org/apache/maven/maven-archiver/2.2/maven-archiver-2.2.jar
[ERROR] urls[3] = file:/C:/Users/dhiagarwal/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar
[ERROR] urls[4] = file:/C:/Users/dhiagarwal/.m2/repository/org/codehaus/plexus/plexus-archiver/1.0-alpha-7/plexus-archiver-1.0-alpha-7.jar
[ERROR] urls[5] = file:/C:/Users/dhiagarwal/.m2/repository/org/apache/felix/org.apache.felix.scr.generator/1.12.0/org.apache.felix.scr.generator-1.12.0.jar
[ERROR] urls[6] = file:/C:/Users/dhiagarwal/.m2/repository/org/ow2/asm/asm-all/5.0.2/asm-all-5.0.2.jar
[ERROR] urls[7] = file:/C:/Users/dhiagarwal/.m2/repository/org/osgi/org.osgi.core/4.2.0/org.osgi.core-4.2.0.jar
[ERROR] urls[8] = file:/C:/Users/dhiagarwal/.m2/repository/org/osgi/org.osgi.compendium/4.2.0/org.osgi.compendium-4.2.0.jar
[ERROR] urls[9] = file:/C:/Users/dhiagarwal/.m2/repository/org/sonatype/plexus/plexus-build-api/0.0.7/plexus-build-api-0.0.7.jar
[ERROR] urls[10] = file:/C:/Users/dhiagarwal/.m2/repository/org/codehaus/plexus/plexus-utils/1.5.8/plexus-utils-1.5.8.jar
[ERROR] Number of foreign imports: 1
[ERROR] import: Entry[import  from realm ClassRealm[project>com.mec:meCommerce.core:0.0.1-SNAPSHOT, parent: ClassRealm[maven.api, parent: null]]]

I have tried jdk 1.7 as well as 1.8

Would I required an unobfuscated uber jar to have this work?