Calling an External or Third Party Service using a Custom Persistence Handler

In this tutorial, we'll show you how to call an external or third party service whenever you need to update an entity in the admin.
For this example, let's say you would like to call a Third Party Address Validation service whenever you update an address on a Store entity.
You can do this pretty easily using a custom persistence handler.

Notice that we've extended the CustomPersistenceHandlerAdapter class and we've implemented the canHandleUpdate and update methods.
We've also injected our own Third Party Address Validation service into the class so that we can validate the address.
For simplicity of this tutorial, we'll only call our custom Address Validation Service on an update of a store.
In Admin usability terms, this means that this custom method would get called on the Edit screen for the entity you are trying to save.

Since we only want our Persistence Handler to run for an Update on a Store entity, let's go ahead and implement the canHandleUpdate method.

@OverridepublicEntityupdate(PersistencePackagepersistencePackage,DynamicEntityDaodynamicEntityDao,RecordHelperhelper)throwsServiceException{Entityentity=persistencePackage.getEntity();try{PersistencePerspectivepersistencePerspective=persistencePackage.getPersistencePerspective();Map<String,FieldMetadata>adminProperties=helper.getSimpleMergedProperties(Address.class.getName(),persistencePerspective);ObjectprimaryKey=helper.getPrimaryKey(entity,adminProperties);StoreadminInstance=(Store)dynamicEntityDao.retrieve(Class.forName(entity.getType()[0]),primaryKey);adminInstance=(Store)helper.createPopulatedInstance(adminInstance,entity,adminProperties,false);Stringaddress1=entity.getPMap().get("address1");Stringaddress2=entity.getPMap().get("address2");Stringcity=entity.getPMap().get("city");Stringstate=entity.getPMap().get("state");Stringzip=entity.getPMap().get("zip");Stringcountry=entity.getPMap().get("country");if(myAddressValidationService.validAddress(address1,address2,city,state,zip,country)){adminInstance=dynamicEntityDao.merge(adminInstance);returnhelper.getRecord(adminProperties,adminInstance,null,null);}thrownewIllegalArgumentException("Store Address is invalid.");}catch(Exceptione){LOG.error("Unable to update entity for "+entity.getType()[0],e);thrownewServiceException("Unable to update entity for "+entity.getType()[0],e);}}

If you look at the implementation for our update method you will notice a couple things. First, we will get the entity we are trying to persist (A Store) off the persistence package.
After this you will notice in the try block a couple lines of boiler plate admin code which retrieves a populated instance of the Store entity. In this example, I also demonstrate
how you may also use the entity PMap() (Property Map) to retrieve custom dynamic fields you may have added to the entity from the inspect phase of the handler.
Either way, we now have access to the fields we want to validate and we can pass that to our custom service. Now, if our address validation returns true, we can go ahead and calldynamicEntityDao.merge() and return our entity record using our utility method `helper.getRecord().

All put together our class would look like this:

@Component("myStoreCustomPersistenceHandler")publicclassStoreCustomPersistenceHandlerextendsCustomPersistenceHandlerAdapter{@Resource(name="myAddressValidationService")protectedMyAddressValidationServicemyAddressValidationService;@OverridepublicBooleancanHandleUpdate(PersistencePackagepersistencePackage){StringceilingEntityFullyQualifiedClassname=persistencePackage.getCeilingEntityFullyQualifiedClassname();try{ClasstestClass=Class.forName(ceilingEntityFullyQualifiedClassname);returnStore.class.isAssignableFrom(testClass);}catch(ClassNotFoundExceptione){returnfalse;}}@OverridepublicEntityupdate(PersistencePackagepersistencePackage,DynamicEntityDaodynamicEntityDao,RecordHelperhelper)throwsServiceException{Entityentity=persistencePackage.getEntity();try{PersistencePerspectivepersistencePerspective=persistencePackage.getPersistencePerspective();Map<String,FieldMetadata>adminProperties=helper.getSimpleMergedProperties(Address.class.getName(),persistencePerspective);ObjectprimaryKey=helper.getPrimaryKey(entity,adminProperties);StoreadminInstance=(Store)dynamicEntityDao.retrieve(Class.forName(entity.getType()[0]),primaryKey);adminInstance=(Store)helper.createPopulatedInstance(adminInstance,entity,adminProperties,false);Stringaddress1=entity.getPMap().get("address1");Stringaddress2=entity.getPMap().get("address2");Stringcity=entity.getPMap().get("city");Stringstate=entity.getPMap().get("state");Stringzip=entity.getPMap().get("zip");Stringcountry=entity.getPMap().get("country");if(myAddressValidationService.validAddress(address1,address2,city,state,zip,country)){adminInstance=dynamicEntityDao.merge(adminInstance);returnhelper.getRecord(adminProperties,adminInstance,null,null);}thrownewIllegalArgumentException("Store Address is invalid.");}catch(Exceptione){LOG.error("Unable to update entity for "+entity.getType()[0],e);thrownewServiceException("Unable to update entity for "+entity.getType()[0],e);}}}

Finally, we will need to hook up our custom persistence handler so that it will run when any entity instance is persisted in the Admin.
We'll simply merge new entries into the bean blCustomPersistenceHandlers