Page 1 of 1

AdminPresentationToOneLookup customCriteria

Posted: Wed Jul 10, 2013 1:49 pm
by fdboles
I would like to limit the selection in a many-to-one lookup to a subset of records available in the target entity. I assume that this can be accomplished using customCriteria, but documentation doesn't explain it's use or syntax. The documentation states "Presumably, one could use this to somehow filter the list of records shown when the user interacts with the lookup widget in the admin UI."

Broadleaf version 2.2.0-GA

Re: AdminPresentationToOneLookup customCriteria

Posted: Sun Mar 16, 2014 12:47 am
by pokemon007
I have the similar question, both for selection list and entity list on entity list view. Can anyone give some instruction, even simple one?

Really appreciate it!

Re: AdminPresentationToOneLookup customCriteria

Posted: Sun Mar 23, 2014 7:33 pm
by phillipuniverse
This 'customCritiera' is used to determine when to execute a CustomPersistenceHandler in the backend. Most of the time you need to execute a custom persistence handler on every modification to a particular entity but sometimes not. Custom persistence handlers have different 'canHandle' methods that you can override to determine if you should execute the corresponding method. For instance, if you return 'true' from a 'canHandleFetch' method then the application will execute your custom persistence handler 'fetch' method.

Here is a small usage example from ProductCustomPersistenceHandler:

Code: Select all

@Override
public Boolean canHandleAdd(PersistencePackage persistencePackage) {
    
String ceilingEntityFullyQualifiedClassname persistencePackage.getCeilingEntityFullyQualifiedClassname();
    
String[] customCriteria persistencePackage.getCustomCriteria();
    return !
ArrayUtils.isEmpty(customCriteria) && "productDirectEdit".equals(customCriteria[0]) && Product.class.getName().equals(ceilingEntityFullyQualifiedClassname);
}
 


Whatever is contained within the 'customCriteria' property will be included in that customCriteria array from the persistence package.

Re: AdminPresentationToOneLookup customCriteria

Posted: Tue Mar 25, 2014 3:40 pm
by pokemon007
I have some problem to get it working. I just want to add a criteria to match merchant of the products queried. Following is my custom fetch code:

Code: Select all

    @Override
    public Boolean canHandleFetch(PersistencePackage persistencePackage) {
        return canHandleAdd(persistencePackage);
    }

    @Override
    public DynamicResultSet fetch(PersistencePackage persistencePackage, CriteriaTransferObject cto, DynamicEntityDao dynamicEntityDao, RecordHelper helper) throws ServiceException {
       try {
           if (cto != null) {
              Long merchantId = BusinessUserState.getMerchantId();
             FilterAndSortCriteria merchantCriteria = new FilterAndSortCriteria("account.id", merchantId.toString());
             cto.add(merchantCriteria);             
           }
           initPersistenceManager();          
           PersistenceModule module = ((InspectHelper)blPersistenceManager).getCompatibleModule(persistencePackage.getPersistencePerspective().getOperationTypes().getFetchType());
           return module.fetch(persistencePackage, cto);
       } catch(ServiceException se) {
          throw se;
       }
       catch(Exception e) {
            throw new ServiceException("Exception when fetch products", e);
       }
    }

    private void initPersistenceManager() {
       if (blPersistenceManager == null) {
          setPersistenceManager();
       }
   }
   
    synchronized private void setPersistenceManager() {
       if (blPersistenceManager == null) {
           this.blPersistenceManager = (PersistenceManager)applicationContext.getBean("blPersistenceManager");
       }       
    }


It throws NPE:

Code: Select all

Caused by: java.lang.NullPointerException
   at org.broadleafcommerce.common.util.dao.DynamicDaoHelperImpl.getSessionFactory(DynamicDaoHelperImpl.java:197)
   at org.broadleafcommerce.openadmin.server.dao.DynamicEntityDaoImpl.getSessionFactory(DynamicEntityDaoImpl.java:740)
   at org.broadleafcommerce.openadmin.server.dao.DynamicEntityDaoImpl.getAllPolymorphicEntitiesFromCeiling(DynamicEntityDaoImpl.java:216)
   at org.broadleafcommerce.openadmin.server.dao.DynamicEntityDaoImpl.getAllPolymorphicEntitiesFromCeiling(DynamicEntityDaoImpl.java:208)
   at org.broadleafcommerce.openadmin.server.service.persistence.module.BasicPersistenceModule.getMergedProperties(BasicPersistenceModule.java:977)


The problem is PersistenceManager's dynamicEntityDao has standardEntityManager = null. Is this the correct approach to implement fetch?

Thank you!

-Charlie

Re: AdminPresentationToOneLookup customCriteria

Posted: Sun Mar 30, 2014 5:09 pm
by pokemon007
I tried another approach, extend AdminProductController and override viewEntityList to add merchant filter as follows:

Code: Select all

    @Override
    public String viewEntityList(HttpServletRequest request, HttpServletResponse response, Model model,
            @PathVariable Map<String, String> pathVars,
            @RequestParam MultiValueMap<String, String> requestParams) throws Exception {
        String sectionKey = getSectionKey(pathVars);
        String sectionClassName = getClassNameForSection(sectionKey);
        List<SectionCrumb> crumbs = getSectionCrumbs(request, null, null);
        PersistencePackageRequest ppr = getSectionPersistencePackageRequest(sectionClassName, requestParams, crumbs, pathVars);

        Long merchantId = BusinessUserState.getMerchantId();
        if (merchantId != null) {
           FilterAndSortCriteria merchantFilter = new FilterAndSortCriteria("merchant.id", String.valueOf(merchantId));
            ppr.addFilterAndSortCriteria(merchantFilter);           
        }
        ...
        ...
        ...
    }


This works perfectly to filter the products by merchant. However, this works only when merchant property of MerchantProduct not be excluded from @AdminPresentation:

Code: Select all

    @ManyToOne(targetEntity = BusinessAccountImpl.class)
   @JoinColumn(name = "BUSINESS_ACCOUNT_ID")
    @AdminPresentation(friendlyName = "MerchanktProduct_Merchant", visibility = VisibilityEnum.HIDDEN_ALL)
    protected BusinessAccount merchant = new BusinessAccountImpl();


This will show all BusinessAccount properties on product's grid view and entity view. It seems @AdminPresentation's visibility = VisibilityEnum.HIDDEN_ALL not working properly. If excluding BusinessAccount from product, the merchant filter won't work because the entities returned from DynamicResultSet does not include merchant property and of course the merchant filter doesn't work.

Is this a bug?

Re: AdminPresentationToOneLookup customCriteria

Posted: Mon Mar 31, 2014 11:14 am
by phillipuniverse
I'm not sure if I would call that a bug; that might be more of an enhancement? I know the 'excluded' attribute on a related entity cascades down to all of its properties, but it looks like the visibility attribute is not. I would argue that this is a valuable enhancement, so please open a ticket on https://github.com/BroadleafCommerce/Br ... rce/issues.

One way that you could get around it would be to mark the 'merchant' property as excluded = true, then override the 'inspect' method for Products in a custom persistence handler to include a 'merchant' property in the map of available properties. At least at that point you would have that property available to you.

Kind of a weird solution though. I think that the visibility attribute should be cascaded down to the sub-properties.

RE: AdminPresentationToOneLookup customCriteria

Posted: Wed Apr 02, 2014 1:11 am
by pokemon007
This seems not working. Adding merchant to the properties list makes the BusinessAccount properties showing on UI. What's worse is that it doesn't filter products by merchant. Here is my code, see if I'm doing something wrong:

Code: Select all

    @Override
    public DynamicResultSet inspect(PersistencePackage persistencePackage, DynamicEntityDao dynamicEntityDao, InspectHelper helper) throws ServiceException {
       try {
          initPersistenceManager();
           Class<?>[] entities = blPersistenceManager.getPolymorphicEntities(persistencePackage.getCeilingEntityFullyQualifiedClassname());
            Map<MergedPropertyType, Map<String, FieldMetadata>> allMergedProperties = new HashMap<MergedPropertyType, Map<String, FieldMetadata>>();
           
            for (PersistenceModule module : ((PersistenceManagerImpl)blPersistenceManager).getModules()) {
                module.updateMergedProperties(persistencePackage, allMergedProperties);
            }

            Map<String, FieldMetadata> p = allMergedProperties.get(MergedPropertyType.PRIMARY);
            Map<String, FieldMetadata> merchantProperties = helper.getSimpleMergedProperties(BusinessAccount.class.getName(), persistencePackage.getPersistencePerspective());
            p.putAll(merchantProperties);
           
//            FieldMetadata idField = merchantProperties.get("id");
//            p.put("merchant.id", idField);
           
            ClassMetadata mergedMetadata = blPersistenceManager.getMergedClassMetadata(entities, allMergedProperties);
           
            return new DynamicResultSet(mergedMetadata);          
       } catch(ClassNotFoundException e) {
          throw new ServiceException(e);
       }
    }


I've also tried to only bring "merchant.id" property back to the list. This avoid showing entire merchant's properties. Again, it doesn't filter product by merchant. Please help!

BYW, I did raise a bug on this issue.

Thank you!

-Charlie

[Workaround]AdminPresentationToOneLookup customCriteria

Posted: Mon Apr 14, 2014 2:19 am
by pokemon007
Just want to share what I did that works well. The workaround is to add an auxiliary property, merchantId. This property is read only and hidden. The sole purpose of this property is for merchant filter.

To make grid list view show only filtered items, extends entity controller, override viewEntityList, adding following line before calling super.viewEntityList
requestParams.add("merchantId", merchantId.toString());

To make AdminPresentationToOneLookup to work, specify filter value through AdminPresentationToOneLookup's customCriteria attribute, extends AdminBasicOperationsController, and override showSelectCollectionItem to handle customCriteria.

Thanks.

-Charlie