Around advices are the most powerful of all as you completely hijack the requested action with your own action that looks, smells and feels exactly as the requested action. This is usually referred to as a proxy design pattern.
users.list => users.aroundHandler() <=> list()
This will allow you to run both before and after advices but also surround the method call with whatever logic you want like transactions, try/catch blocks, locks or even decide to NOT execute the action at all.
You can do it globally by using the aroundHandler() method or targeted to a specific action around{actionName}().
Examples
// executes around any actionfunctionaroundHandler(event,targetAction,eventArguments,rc,prc){}// executes around the list() action ONLYfunctionaroundList(event,targetAction,eventArguments,rc,prc){}// Around handler advice for transactionsfunctionaroundHandler(event,targetAction,eventArguments,rc,prc){// log the calllog.debug("Starting to execute #targetAction.toString()#" );// start a transaction transaction{// prepare arguments for action callvar args = { event = arguments.event, rc = arguments.rc, prc = arguments.prc };structAppend( args, eventArguments );// execute the action nowvar results =arguments.targetAction( argumentCollection=args ); }// log the calllog.debug( "Ended executing #targetAction.toString()#" );// return if it existsif( !isNull( results ) ){ return results; }}// Around handler advice for try/catchesfunctionaroundHandler(event,targetAction,eventArguments,rc,prc){// log the callif( log.canDebug() ){log.debug( "Starting to execute #targetAction.toString()#" ); }// try blocktry{// prepare arguments for action callvar args = { event = arguments.event, rc = arguments.rc, prc = arguments.prc };structAppend( args, eventArguments );// execute the action nowreturnarguments.targetAction( argumentCollection=args ); }catch(Any e){// log itlog.error("Error executing #targetAction.toString()#: #e.message# #e.detail#", e);// set exception in request collection and set view to renderevent.setValue( "exception", e).setView( "errors/generic" ); }}
The arguments received by these interceptors are:
event : The request context reference
targetAction : The function pointer to the action that got the around interception. It will be your job to execute it (Look at samples)
eventArguments : The struct of extra arguments sent to an action if any
rc : The RC reference
prc : The PRC Reference
Exceptions & Only Lists
You can fine tune these interception methods by leveraging two public properties in the handler:
this.aroundhandler_only : A list of actions that the aroundHandler() action will fire ONLY!
this.aroundhandler_except : A list of actions that the aroundHandler() action will NOT fire on
// only fire for the actions: save(), delete()this.aroundhandler_only ="save,delete";// DO NOT fire for the actions: login(), doLogin(), logout()this.aroundhandler_except ="login,doLogin,logout"