AOP in JavaScript using Humax Framework

Page 3 of 3
  1. Introduction
  2. Facet Programming
  3. More AOP & Metadata Driven Approach

More AOP & Metadata Driven Approach

AroundAdvice

In the previous section, we have seen the usage of BeforeAdvice and AfterAdvice. In this section, we are going to see how to use AroundAdvice. We have taken the same code which we used in the previous section.

In this section, we have made one change on fillInventory():

...
fillInventory : function(quantity)
{

if(quantity <= 0)
throw new Humax.Exception("Invalid quantity",
"HxTest.Inventory.fillInventory()");

if(this._available + quantity <= this._capacity)
{
this._available += quantity;
}else
{
this.OnStockAlert(Humax.EventAction.Trigger, "Stock full",
quantity,this._available);
}
},
...

In the above code, see the bold text. If the number of item to fill is zero or less than zero, it throws exception with message "Invalid quantity". Let us assume that the caller of this method do not write exception handling in most of the code like:

function fillButton_onclick()
{
document.getElementById("output").innerHTML = "";
myInventory.fillInventory(parseInt(
document.getElementById("fillTextBox").value)
);

document.getElementById("status").innerHTML =
"Available Stock: " + myInventory.getAvailableStockCount();
}

But he needs to implement exception handling on all part wherever he called fillInventory(). This is called code scattering as we learned in previous section. But by implementing AroundAdvice in InventoryValidatorFacet, we can achieve this easily. Now we are going to implement AroundAdvice in InventoryValidatorFacet. For your convenience, the modified or newly inserted code is in bold.

HxTest.InventoryValidatorFacet.prototype = 
{
beforeFillInventory : function(sourceObject, joinPointOriginalArgs)
{
alert("Going to fill");
},

afterFillInventory : function(sourceObject, joinPointOriginalArgs)
{
if(joinPointOriginalArgs[0] > 0)
alert(joinPointOriginalArgs[0] + " item(s) has been filled");
},

aroundFillInventory : function(sourceObject, sourceMethod, joinPointOriginalArgs)
{
try
{
//callSource is the Facet method to invoke actual joinpoint implementation
this.callSource(sourceObject, sourceMethod, joinPointOriginalArgs);
}catch(e)
{
alert(e.getMessage());
}
},

attachHandlers : function()
{
this.callBaseMethod("attachHandlers");
this.BeforeAdvice(Humax.EventAction.AttachHandler,
this.beforeFillInventory, this);
this.AfterAdvice(Humax.EventAction.AttachHandler,
this.afterFillInventory, this);
this.AroundAdvice(Humax.EventAction.AttachHandler,
this.aroundFillInventory, this);

}
}

In order to stop displaying message on afterFillInventory, if quantity is less than or equal to zero, a condition is applied in afterFillInventory().

callSource Method

As we know that aroundFillInventory has one more argument called sourceMethod which refers the current join point. The next big thing is how can we invoke current join point within aroundFillInventory. Facet provides a method named callSource() which actually invoke the join point. You can write your AroundAdvice implementation around this.callSource()

Now execute the application.

Metadata using Facet

We can use metadata to pass information to various programming components which can be parsed at runtime by the applied components. The information can be anyone of the following:

  • Code versioning information
  • Descriptive information that require to change the program flow at run time.

Humax allows you to declare Metadata by Facet which may or may not be an aspect. Assume that, in the HxTest.Inventory class, we have planned to supply a key code to fillInventory() and orderItem() methods. These methods simply parse the content and proceed further if it is valid.

Declaring Metadata

HxTest.InventoryPassportFacet = function(keyCode)
{
this.base();
this.$usage = Humax.FacetUsage.AllowMultiple;
this._keyCode = keyCode;
}

HxTest.InventoryPassportFacet.prototype =
{
getKeyCode : function() { return this._keyCode;}
}

Humax.declareClass("HxTest.InventoryPassportFacet",
HxTest.InventoryPassportFacet, Humax.Facet);

In the above code, we have defined a facet InventoryPassportFacet without advice support means that we stated that this facet is purely for metadata. And it has one getter method getKeyCode().

Finally, we apply this facet on Inventory class members fillInventory and orderItem at some other place of the code.

Humax.applyFacet(new HxTest.InventoryPassportFacet("abc123zyx987"), 
HxTest.Inventory, "fillInventory", "orderItem");

As explained, these methods should get the currently passed keyCode value for further process, in our case, we are going to simply displays the keycode. See the bold lines in the following code.

fillInventory : function(quantity)
{
var facet = Humax.Facet.getFacet("HxTest.InventoryPassportFacet", this, "fillInventory");
alert("This is fill inventory: Your key code is " + facet.getKeyCode());


if(quantity <= 0)
throw new Humax.Exception("Invalid quantity",
"HxTest.Inventory.fillInventory()");
if(this._available + quantity <= this._capacity)
{
this._available += quantity;
}else
{
this.OnStockAlert(Humax.EventAction.Trigger,
"Stock full", quantity,this._available);
}
},

orderItem : function(quantity)
{
var facet = Humax.Facet.getFacet("HxTest.InventoryPassportFacet",
this, "orderItem");
alert("This is order item: Your key code is " + facet.getKeyCode());


if(quantity <= (this._available - this._reorderLevel))
{
this._available -= quantity;
}else
{
this.OnStockAlert(Humax.EventAction.Trigger,
"Fill the stock, reached minium reorder level", quantity,this._available);
}
}

Humax.Facet class provides getFacet() method to get a specified facet which applied and specified for the current exeuction context. It also provides getFacets() to get all facets applied and specified for the current execution context.

Now, execute the program.

For more details or your contribution in Humax web framework, visit http://humax.sourceforge.net or
write me to udooz@hotmail.com.

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.” - Rich Cook