2

I am using blc.version 5.1.5-GA.

When adding targeted products to a product group, the listgrid only displays defaultSku.name. I would like to add additional information to the listgrid.

Here's the relevant entity definition:

@OneToMany(targetEntity = ProductProductGroupXrefImpl.class, mappedBy = "productGroup",
    cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blProducts")
@BatchSize(size = 50)
@AdminPresentationAdornedTargetCollection(friendlyName = "ProductGroup_Products", 
    group = GroupName.Details, order = 3000,
    joinEntityClass = "com.broadleafcommerce.merchandisinggroup.domain.ProductProductGroupXrefImpl",
    targetObjectProperty = "product",
    parentObjectProperty = "productGroup",
    gridVisibleFields = {"defaultSku.name"})
protected List<ProductProductGroupXref> productXrefs = new ArrayList<>();

Here's some things I've tried with no success, each <mo:field> block is a separate thing I tried:

<mo:overrideItem ceilingEntity="org.broadleafcommerce.core.catalog.domain.ProductGroupImpl">
    <mo:field name="defaultSku.ean, defaultSku.name">
        <mo:gridVisibleField value="productXrefs"/>
    </mo:field>

    <mo:field name="productXrefs">
        <mo:gridVisibleField value="defaultSku.name, defaultSku.ean"/>
    </mo:field>

    <mo:field name="defaultSku.ean">
        <mo:gridVisibleField value="productXrefs"/>
    </mo:field>

    <mo:field name="productXrefs">
        <mo:gridVisibleField value="defaultSku.ean"/>
    </mo:field>
</mo:overrideItem>

I was restarting my tomcat server each time to ensure the changes were actually being loaded. Is there anything I can debug into and inspect in order to confirm this?

Someone had a similar question and he was never able to get XML overriding working. This question also needs an answer: How to override the @AdminPresentation for existing attributes.

2 Answers2

3

I believe the correct format would be:

<mo:overrideItem ceilingEntity="com.broadleafcommerce.merchandisinggroup.domain.ProductGroup">
    <mo:field name="productXrefs">
        <mo:gridVisibleField value="defaultSku.name"/>
        <mo:gridVisibleField value="defaultSku.ean"/>
    </mo:field>
</mo:overrideItem>

Note that the ceilingEntity is the interface for product group, not the Impl.

  • This was correct, but I also later discovered I was using the wrong package name. ProductGroup is in com.broadleafcommerce.merchandisinggroup.domain in my version of blc. – Spencer Stewart Oct 30 '19 at 14:26
  • Sorry about that, I copied over the package name from your question and didn't validate it. Thanks for the edit / reply below! – KeeperofDusk Oct 30 '19 at 15:39
2

KeeperofDusk's answer technically answered the original question so I accepted it, but the listgrid still wasn't displaying additional gridVisibleFields. It turns out I had the wrong package name in the ceilingEntity attribute.

In my version of blc, the package for ProductGroup is in com.broadleafcommerce.merchandisinggroup.domain, not org.broadleafcommerce.core.catalog.domain.

I debugged into AbstractFieldMetadataProvider#getTargetedOverride.

protected Map<String, MetadataOverride> getTargetedOverride(DynamicEntityDao dynamicEntityDao, String configurationKey, String ceilingEntityFullyQualifiedClassname) {
        if (metadataOverrides != null && (configurationKey != null || ceilingEntityFullyQualifiedClassname != null)) {
            if (metadataOverrides.containsKey(configurationKey)) {
                return metadataOverrides.get(configurationKey);
            }
            if (metadataOverrides.containsKey(ceilingEntityFullyQualifiedClassname)) {
                return metadataOverrides.get(ceilingEntityFullyQualifiedClassname);
            }
            Class<?> test;
            try {
                test = Class.forName(ceilingEntityFullyQualifiedClassname);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
            if (test.isInterface()) {
                //if it's an interface, get the least derive polymorphic concrete implementation
                Class<?>[] types = dynamicEntityDao.getAllPolymorphicEntitiesFromCeiling(test);
                return metadataOverrides.get(types[types.length-1].getName());
            } else {
                //if it's a concrete implementation, try the interfaces
                Class<?>[] types = test.getInterfaces();
                for (Class<?> type : types) {
                    if (metadataOverrides.containsKey(type.getName())) {
                        return metadataOverrides.get(type.getName());
                    }
                }
            }
        }
        return null;
    }

On this exact line: return metadataOverrides.get(types[types.length-1].getName()); I was always getting null. Proper behavior is that this line should return a LinkedHashMap of the field and its FieldMetadataOverrides.

The types[types.length-1].getName() should resolve to the fully qualified classname for the target ceiling entity. I tried manually evaluating that line in my IDE but kept getting null. At this point I still haven't realized the wrong fully qualified classname was getting passed in.

Then I tried debugging into the controller endpoint in AdminBasicEntityController.

@RequestMapping(value = "/{id}/{collectionField:.*}/add", method = RequestMethod.GET)
    public String showAddCollectionItem(HttpServletRequest request, HttpServletResponse response, Model model,
            @PathVariable Map<String, String> pathVars,
            @PathVariable(value = "id") String id,
            @PathVariable(value = "collectionField") String collectionField,
            @RequestParam MultiValueMap<String, String> requestParams) throws Exception {
        String sectionKey = getSectionKey(pathVars);
        String mainClassName = getClassNameForSection(sectionKey);
        List<SectionCrumb> sectionCrumbs = getSectionCrumbs(request, sectionKey, id);
        ClassMetadata mainMetadata = service.getClassMetadata(getSectionPersistencePackageRequest(mainClassName,
                sectionCrumbs, pathVars)).getDynamicResultSet().getClassMetaData();
        Property collectionProperty = mainMetadata.getPMap().get(collectionField);
        FieldMetadata md = collectionProperty.getMetadata();

It turns out BLC_ADMIN_SECTION associates a section key with a fully qualified classname which is used to resolve the metadata for the entity. I thought the problem was that the wrong fully qualified classname was entered into the ceiling_entity column, so I changed it to org.broadleafcommerce.core.catalog.domain.ProductGroup, which didn't solve the problem. That also makes no sense, because I don't think any information about ProductGroup would render in that admin page if that were the case.

Finally I went to check if that fully qualified classname even exists, and that's when I realized I went on a wild goose chase for 10 hours.

The lesson learned for future googlers is to use auto-complete.