JavaScript Chaining Promises to Promises

October 28, 2014

When you create a Promise you can chain asynchronous behavior by using the then(success,fail) method. The success and fail are callback functions invoked appropriately when the promise is resolved or rejected. Note that since ‘then(…)’ returns a promise, this technique is called promise chaining: p.then(…).then(….).

What I discuss in this post are two subjects
1. How to ‘stitch’ multiple promises together?
2. How to ‘splice’ in an object into a promise chain?
3. How to chain using a promise object as an argument?

What if in a complex application you already have promises objects and want to create promise chains linking these objects to each other? How would you do this with ‘then’ methods? Amazingly, in most examples of using Promises on the web this simple scenario is never presented directly. Granted it doesn’t *seem* to be relevant.

Here is the source of a simple demo based on one of the Dojo Deferred examples. It is ‘normal’ promise chaining. I’m using this as the basis for the investigation presented here. The output displayed on page should be: completed with value: 75

The actual chaining ‘stitching’ is setupTrans().then(function(x){return action()}).then(outputValue);

<!DOCTYPE html>
<html >
<head>

<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"  data-dojo-config="async:false"></script>
	
<script>
require(["dojo/when", "dojo/Deferred", "dojo/dom", "dojo/on", "dojo/domReady!"],function(when, Deferred, dom, on){
	  var balance = 100;

	  function asyncProcess(x){
	    var deferred = new Deferred();
	
	    setTimeout(function(){
	      if(x === 'plus' || x === 'minus'){
	      	 x === 'plus' ? (balance += 25) : (balance -= 25);
	      } 
	      deferred.resolve(balance);
	    }, 1000);
	
	    return deferred.promise;
	  }

	  function setupTrans(){
	  	return asyncProcess('z');
	  }

	  function debitAccount(){
		return asyncProcess('minus');
	  }
	
	  function creditAccount(){
		return asyncProcess('plus');
	  }

	  function outputValue(value){
	    dom.byId("output").innerHTML += "<br/>completed with value: " + value;
	  }
	  
	  on(dom.byId("startButton"), "click", function(){
	  	var debit = true;
	  	var action = debit ? debitAccount : creditAccount;
	  	
	  	setupTrans()
	  	.then(function(x){return action()})
	  	.then(outputValue);
	  	
	  });
});
</script>
</head>
<body class="claro">
    <h1>Output:</h1>
	<div id="output"></div><p />
	<button type="button" id="startButton">Start</button>
</body>
</html>

What is ugly is the inline function. Luckily I found the “Flattening Promise Chains” article where the author shows how to get rid of the function and simplify. However that article didn’t answer my question, how can you simply and directly chain promise objects. What the article showed is that you have to use the correct structure or design. Well, of course, but …


Answer
I thought this would be difficult. The Dojo documentation page never mentions that instead of the first ‘then’ argument being onFulfilled handler function it could be an actual promise object. But this is mentioned in specs such as the Promises/A+ specification. Or does it? The ‘Promise resolution procedure’ seems to mix compile time view with runtime, or I’m reading it incorrectly. Q documentation is very good on this. Will have to research further.

To directly chain separate promise chains the above code sample is modified as follows by just using an existing promise as the argument to another chains then(…) method. However, this can only be done using a promise returning function.

  on(dom.byId("startButton"), "click", function(){
  	var debit = true;
  	var action = debit ? debitAccount : creditAccount;
  	
  	setupTrans()
  	.then(action)
  	.then(outputValue);
  	
  });

Or, to inline the decision:

  on(dom.byId("startButton"), "click", function(){
  	var debit = true;
  	
  	setupTrans()
  	.then(debit ? debitAccount : creditAccount)
  	.then(outputValue);
  	
  });


Chaining using actual promise objects inside the then(f,r) is made easy using the approach shown next, using “scalars”.

Chaining values into promise chains
While looking at this subject I thought about a situation where we want to directly insert a known value into the chain so that the next ‘link’ will use this as the prior handler’s return value.

We have a chain, and I want to put the great Answer in there. This won’t work: var p1 = promiseReturningFunction().then(…).then(’42’).then(….).

Sure you can wrap ’42’ in an inline function then(function(){return ’42’}), but that is yucky. How about a function that does that:

     /** return a function that returns the value */
     function now(value){
    	  return function(){return value;};
      }

Now you can do: var p1 = async().then(…).then(now(’42’)).then(….);

Here is the prior source code with the changes. This is just some of the script changes. The output on screen is:

completed with value: 75
completed with value: Goodbye

      /* ...  */

      function outputValue(value){
        dom.byId("output").innerHTML += "<br/>completed with value: " + value;
      }
      
      function now(value){
    	  return function(){return value;};
      }
      
      on(dom.byId("startButton"), "click", function(){
        var debit = true;
        var action = debit ? debitAccount : creditAccount;
        
        var promise1 = setupTrans()
        .then(debit ? debitAccount : creditAccount)
        .then(outputValue)
        .then(function(){
        	console.log("now do another promise chain...");
        });
        
        promise1.then((now('Goodbye'))).then(outputValue);
        
      });


Using promises objects directly in then(f,r) by using now(x)
With the Promises implementation in Dojo, you can’t use promiseObject.then(anotherPromiseObject). And you can’t use promiseObject.then(when(anotherPromiseObject)). At least, I haven’t figured how to do it.

With the now(x) function shown above, this is easy. The code below will output:

completed with value: 75
completed with value: 100
completed with value: undefined
completed with value: finished both chains

     function now(value){
    	  return function(){return value;};
      }
      
      on(dom.byId("startButton"), "click", function(){
        var debit = true;
        var action = debit ? debitAccount : creditAccount;
        
        var promise1 = setupTrans()
        .then(action)
        .then(outputValue)
        .then(function(){
        	console.log("now do another promise chain...");
        });
        
        debit = false;
        action = debit ? debitAccount : creditAccount;
        var promise2 = setupTrans()
        .then(action)
        .then(outputValue);
        
        promise1
        .then(now(promise2)).then(outputValue)
        .then(now("finished both chains"))
        .then(outputValue);
        
      });
});

Further reading

  1. Original post
  2. Flattening Promise Chains
  3. A Deeper Dive Into JavaScript Promises
  4. How-to Compose Node.js Promises with Q
  5. Promise Anti-patterns
  6. dojo/when
  7. q
  8. General Promise Resources
  9. Promises/A+

How to use multiple views in Notepad++

May 19, 2012

Good editors always have some support for showing multiple editor windows. This is supported in many ways. See this for a comparison of the available document interfaces.

Multiple Views
NotePad++
I was happily surprised to find that Notepad++ also supports this. The trick is to right click on an edit window’s tab and choose “Move to other view” or “Clone to other view”.

Eclipse IDE
By the way, Eclipse IDE also supports multiple docking of edit views. You can even open two views into the same file. However, Notepad++ allows you to synchronize this. Which, afaik, Eclipse does not.

Multiple instances
While the above is great, sometimes you want two Notepad++ instances to, for example, open them each in their own display monitor. For that you just have to add to the notepad exe startup: -multiInst. For example on my Windows 7 instance my Notepad++ shortcut has:
“C:\Program Files (x86)\Notepad++\notepad++.exe” -multiInst

References
Comparison of document interfaces
Managing two views in a single Notepad++ instance


What is Cloud Computing?

May 12, 2012

Someone from the non-technical business side asked me what is this Cloud computing all about. If you search for the term you find a bunch of definitions and descriptions. For example, on Wikipedia:

“Cloud computing refers to the delivery of computing and storage capacity as a service to a heterogeneous community of end-recipients.”
http://en.wikipedia.org/wiki/Cloud_computing.

That doesn’t sound like anything new. We had similar things even in the sixties. You have to read more of the above article to see the differences. But, to see what it really means a blog post, “Startups are Creating a New System of the World for IT“, puts it in context.


Groovy script to bootstrap a Gradle Project

March 8, 2012

I took Ted Naleid’s “Quick Shell Function to Bootstrap a Gradle Groovy Project” example code and converted it to a Groovy script.

Listing 1.

// NewGradle.groovy
// Author: Josef Betancourt
// Based on T. Naleid's shell script 

println "Creating files for new Gradle project ..."

new File(".gitignore").withPrintWriter{ w ->
     "*.un~,*.iml,*.ipr,*.iws,build,.gradle".split(",").each{ 
         w.println(it)
     }
}

new File("build.gradle") << ="""\
apply plugin: 'groovy'
apply plugin: 'idea'
apply plugin: 'eclipse'
 
repositories {
    mavenCentral()
}
 
dependencies {
    groovy 'org.codehaus.groovy:groovy:1.8.6'
    compile 'org.apache.ivy:ivy:2.2.0'
}
 
task createSourceDirs(description : 
   'Create empty source directories for all defined sourceSets') 
   << {
        sourceSets*.allSource.srcDirs.flatten().each { 
            File sourceDirectory ->        
            if (!sourceDirectory.exists()) {
                println "Making \$sourceDirectory"
                sourceDirectory.mkdirs()
            }
        }
}
 
idea {
    project {
        jdkName = '1.6'
    }
}

""" // end content

"cmd /c gradle createSourceDirs".execute()

"cmd /c git init".execute()

Thread.start{
	sleep 5000 // allow time for all files to be created
	new File(".").eachFile{
		println it
	}
}

Not expert Groovy, but was easy to do. The bulk of it is the creation of a “here” doc using Groovy’s triple quote string. I didn’t duplicate the last line of Naleid’s script: “ls -a1 && find src # list all created assets”.

This script is not fully cross-platform. The invocation of shell commands at the end are in the Windows format. Left as an exercise to reader is the use of inline AntBuilder to reuse Ant’s exec task. :-)

Updates
2012-03-09: Tweaked the source. Removed use of two temp variables.
2012-03-09: Added the Eclipse plugin. Now after creating the Gradle project executing eclipse will create the eclipse project: gradle eclipse
Or instead generate the Idea project: gradle idea.

Further Reading

  1. Copy of this post
  2. Groovy (Programming language)
  3. Groovy
  4. Gradle
  5. Quick Shell Function to Bootstrap a Gradle Groovy Project
  6. Strings and GString
  7. Groovy JDK extensions
  8. Executing External Processes
  9. Using Gradle to Bootstrap your Legacy Ant Builds

Off Topic


Access local drive with UNC and mklink on Windows

March 4, 2012

I set up a Tomcat app server on a ‘virtual’ hard drive. The virtual drive is assigned a local hard drive letter. But when a Groovlet attempts to access a local file, the file path used is on the default local drive, C:. How to allow access to the non-local file?

Symbolic links
There are probably many ways to do this and of course corresponding security concerns. One of these is to use Universal Naming Convention (UNC) paths. My quick approach is to just use file directory symbolic links. These are supported in most windows versions. On Windows 7 the MKLINK command is available.

Example
You want to access the folder w:\a\b\c on the virtual drive. On the “real” drive you create a link:

c:
mkdir a\b
mklink /D c w:\a\b\c

Now when the app server access the “c” folder via a UNC, \\mymachine\a\b\c, it will find it.

Duplicate post on other blog: Access local drive with UNC and mklink on Windows


Virtual Machine Applicance for development environment

January 1, 2012

Configuration of a development environment can be very time consuming, error prone, or difficult. This is especially true when investigating or getting up to speed on a new technology or framework. In a corporate environment this is a also a drain on resources and existing developer staff who must take the time to prep a new developer.

One approach to mitigate this is to use a Virtual Appliance.

Virtual appliances are a subset of the broader class of software appliances. Installation of a software appliance on a virtual machine creates a virtual appliance. Like software appliances, virtual appliances are intended to eliminate the installation, configuration and maintenance costs associated with running complex stacks of software.

A virtual appliance is not a complete virtual machine platform, but rather a software image containing a software stack designed to run on a virtual machine platform which may be a Type 1 or Type 2 hypervisor. Like a physical computer, a hypervisor is merely a platform for running an operating system environment and does not provide application software itself. — Virtual Appliance

Creating a Virtual Machine Applicance
The available VM software such as Oracle VirtualBox and the VMware VM have facilities to generate appliances. Thus, when a functioning development environment is created by a lead tech or group, an appliance can be generated for the rest of the team. This appliance can even be provided using a Virtual Desktop Infrastructure (VDI).

Open Virtualization Format
While a VM system can be used to create individual VM instances that can be reused, a more recent technology (supported by some vendors) is the use of OVF:

… is an open standard for packaging and distributing virtual appliances or more generally software to be run in virtual machines.

The standard describes an “open, secure, portable, efficient and extensible format for the packaging and distribution of software to be run in virtual machines”. The OVF standard is not tied to any particular hypervisor or processor architecture. The unit of packaging and distribution is a so called OVF Package which may contain one or more virtual systems each of which can be deployed to a virtual machine.

An OVF package consists of several files, placed in one directory. A one-file alternative is the OVA package, which is a TAR file with the OVF directory inside. — http://en.wikipedia.org/wiki/Open_Virtualization_Format

Using ready made appliances
Each VM vendor can/does make available an appliance marketplace. Thus, one can find ready-made LAMP based environments with a development software stack, for example.

Alternative 1, an installable virtual disk
Where resources are constrained, such as places where developers are still on 3GB of ram and ancient PCs, a Virtual Machine is just not going to cut it.

One easy alternative is to create a dev environment on an installable soft hard drive. TrueCrypt can be used for this purpose. One simply create a true crypt volume, which is just a single file. Then creates the desired dev env in that volume, and that file can now be copied to load into other dev’s workstations as a new hard drive.

TrueCrypt is really for security and privacy concerns, it encrypts data, so may not be ideal for this application. Since TrueCrypt is so useful as a virtual disk, it would be great if it had the option of not encrypting content. But, that would perhaps be outside of its feature space. For that the next alternative is available.

Alternative 2, use VHD files
An alternative is using something directly targeted at virtual disks such as the VHD file format. However, this does not seem to have easily useful public gui or command support (for the end user: developer).

On Windows following the instructions here and using these Send To scripts will allow one to seamlessly use vhd files as mountable hard disk volumes.

Note that Windows 8 will support native mounting of ISO and VHD files.

Further Reading


KARSH KALE plays “MILAN” LIVE


Exception verification using fault injection via AOP

November 13, 2011

A simple example is used to show how to use Aspect Oriented Programming to provide fault injection.

Intro

A few months ago I was looking at Java code and thinking there must be a better way to see if this will really work, if there are any issues in how the program would react to exceptional conditions.  I could write some unit tests or force some problems to see if the exception handling is correct and the log file output is really useful.  But is there another way?

I got a solution after a while of thinking: Insert faults.  Now how to do that in an easy and  maintainable way? Not a new idea of course. After doing a web search I found some interesting references.

Funny, today at work I was extending an application and one of the support objects was failing. Turned out to be an index out of bounds problem. The method had adequate exception handling but, of course, an index out of bounds scenario was not tested. In this case the problem would not occur in production (hmmm), but it definitely occurred during development, and was not handled correctly.

Exception Handling

There are many references of correct exception handling strategies and best practices.  However, when creating applications, the developer must still make critical creative decisions about how to handle an exception.    That decision may not be a wise one.  And even if it is, may later prove to have been very unwise since the system requirements and implementation may have changed due to maintenance or requirement evolution.

Testing Approaches

Using various testing methodologies a subsystem can be exhaustively tested for exception handling.  Yet, most testing methods require that the subsystems be isolated in some manner.   This, though very valuable, can give fatal false confidence that the system will behave in a predictable manner in responding to exceptional conditions.

The prime example of this is within the Unit Testing methodologies.  Since Unit Tests are tests of isolated components, they do not test actual exception handling in the live system.  A perfect component can still contribute to system failure when it is used incorrectly or uses other components incorrectly.    For example, a unit test can show that class X’s methods correctly handle and when necessary throw the perfect exception.   That means nothing if components that interact with X don’t correctly use those exceptions:  they swallow, mask, or mistakenly catch them when there is nothing they can do.

Thus, one needs to use Integration Testing to test assemblages of components.  But, we are still back with the same shortcoming as with Unit Testing. Thus we would next need various forms of system testing.  And, that system testing must be a White Box test.  A Black Box test wherein an interface is exercised with various inputs (such as in web test systems or by QA personnel), will not necessarily invoke the full internal API/SPI between components that could be part of a complicated call chain.  Why?  Because, the interface, such as a browser client, will have (we hope) the validation, security, and logging layers implemented so that by the time a system test workflow enters the deep system components within the client or middleware, there is no way to influence the target component state into programmatic intentional failure mode.

If there is no way to exercise a run time trajectory, then why bother? The reason is that exceptional conditions are exceptional. Resources can be exhausted, systems not available, and so forth. The rule of Fail Fast may not be enough if collaborating components are not exceptionally responsive.

Fault Injection

To see if a system is responding to exceptional conditions, one must wait for those conditions or create them.    Analogously to Fuzz Testing we can dynamically and randomly insert faults.  In Fuzz Testing, inputs are manipulated to a system under test.  In Fault Injection we have to manipulate inputs inside the real system, within the components themselves.  And as in Fuzz Testing, we can employ various strategies to do so, such as randomized faults, etc.   Of course, this system is not the deployed production system, it is the real system in a test environment, an internal full deployment.

Some approaches are: source modification, source macros, annotations, dependency injection (IOC), and Aspect Oriented Programming (AOP). Of course, there are many other techniques as found in open/closed projects, commercial products, and the research community.

Fault Injection using AOP

Since using the real system is required, a viable approach is to use the Instrumentation already available in the Java system. We could dynamically insert code that forces exceptions. AOP as implemented by the AspectJ language can already do this.

The major advantage of using AOP is that the source is not changed in any way. AspectJ is the state of the art in the Java ecosystem for using AOP.

Other approaches

Monitoring

BTrace (a Java oriented approach comparable to DTrace) is very interesting. However, since, like DTrace, it is meant to be safe, defect injection may not be doable. But, see this post on an unsafe mode for BTrace.

Source modification

One way of injecting failure is just to edit the source code and add strategic code that will cause the instigating failure.  An advanced form of this is Mutation Testing.   Code changes could be:  arguments with wrong values, nulls, deliberately thrown exceptions, etc.  For example, one can simply create a method that throws a runtime exception:


     *** DON'T DO THIS ***

    public static void REMOVE_XXX_FROM_XXX_SOURCE(){
       if(true){
          throw new NullPointerException(
             "\n\t****** DELIBERATE RUNTIME EXCEPTION*****\n");
       }
    }
    

Then insert invocations to this method at strategic points in the code, deploy to a test environment, and see if the expected results are obtained, such as logging output that can identify the cause, or that no side effects are recorded, such as incorrect data storage.

This is a low tech and error prone approach.  Most importantly, this is dangerous.  In the mad development rush to meet deadlines and also eat lunch, this code could make it into production!  Even with that horrific method name, it will wind up in production!  One would have to create deployment filters that stop the process if any “fault” inducing code is included.  Another reason why this is not a good approach is that it doesn’t scale very well.   Forcing exceptions is just one type of verification.  Another is setting values outside of expected ranges or states.  Thus, one would need many different kinds of source code insertions. 

Of course, Unit and Behavior based testing tools sets can supply these required verifications if included into the system as Built-In Self-Tests (BIST).

Built-In Self-Test

In the hardware realm, BIST as found in, for example, IEEE 1149.1 JTAG, has been very successful. On the software side, there is ongoing research on how to implement BIST-like capability. This would make Brad Cox’s concept of the “Software IC” even more powerful.

Macros

A somewhat viable approach to source code fault insertion is instead of inserting the faulting code,  insert “include” macros in the original source code that indicates what fault insertion should be done at a location.  A fault injection preprocessor can scan and insert the fault framework’s invocations to accomplish the requirement.  The source code build process can then simply enable or disable the use of the preprocessor.  This would however still require source code modification and an extra maintenance nightmare.  When the code changes the macros may also require change.

Annotations

Instead of macros, we could also use Annotations.  Annotations could explicitly state the runtime exceptional behavior “service level agreements” at the component level. These SLA could then be systematically manipulated to test if they really hold at the system level.

Dependency Injection

One can also inject exceptional behavior by dependency injection, using programmatic, declarative, or annotations, faulted components could be inserted (or created via Aspect Oriented Programming) into the target system.

AOP Demonstration

In listing one below, an ATM class uses a service to do some banking.

/**
 * Driver class for example. 
 * For a real system see:  https://bitbucket.org/aragost/javahg/
 * @author jbetancourt
 */
public class ATM {
	private BankService service = new BankService(1000);

	/** 
	 * Perform a banking action.
	 */
	public void transaction(){	
		{
			service.deposit(100L);
			service.withdraw(200L);
		}
		
		service.statement();		
	}
	
	/** Application entry point	 */
	public static void main(String[] args) {
		new ATM().transaction();
	}
}

Listing two is the BankService being used. Of course, a real service would be more complex.

/**
 * Example service.
 */
public class BankService {
	// Use Long to allow example's null for failure
	// injection.

	private BigDecimal balance;
	
	public BankService(long savings){
		this.balance = new BigDecimal(savings);
	}
	
	/** */
	public void deposit(Long amount){
		balance = balance.add(new BigDecimal(amount));
		System.out.println("Deposit:  " + amount);
	}
	
	/** */
	public void withdraw(Long amount){
		balance = balance.subtract(new BigDecimal(amount));
		System.out.println("Withdraw: " + amount);
	}
	
	/** */
	public void statement() {
		System.out.println("Balance:  " + balance);		
	}	
	
} // end BankService

A example Non-faulted execution result is:

Report: pointcut usage
  withdrawCut:   true ->  false
  depositCut:  false ->  false
       Deposit: 100
      Withdraw: 200
       Savings: 900

When we run the demo program we get:

Exception at the withdraw method.

Report: pointcut usage
withdrawCut:   true ->   true
depositCut:  false ->  false
Deposit: 100
Exception in thread "main" java.lang.NullPointerException
   at BankService.withdraw_aroundBody2(BankService.java:15
   at BankService.withdraw_aroundBody3$advice(BankService.java:81)
   at BankService.withdraw(BankService.java:1)
   at Main.main(Main.java:16)

Exception at the deposit method.

Report: 
pointcut usage
withdrawCut:   true ->  false
depositCut:  false ->   true
Exception in thread "main" java.lang.NullPointerException
   at BankService.deposit_aroundBody0(BankService.java:9)
   at BankService.deposit_aroundBody1$advice(BankService.java:81)
   at BankService.deposit(BankService.java:1)
   at Main.main(Main.java:15)

All pointcuts enabled.

Report: 
pointcut usagewithdrawCut:   true ->   true
depositCut:  false ->   true
Exception in thread "main" java.lang.NullPointerException
   at BankService.deposit_aroundBody0(BankService.java:9)
   at BankService.deposit_aroundBody1$advice(BankService.java:81)
   at BankService.deposit(BankService.java:1)
   at Main.main(Main.java:15)

Implementation

Now to test the exceptional behavior we want to fault the deposit and withdraw methods.
First we have a way of specifying what we want to fault by using a JSON configuration file:

{
	"__comments":[
		"File: properties.json"
	],
	"settings":{
		"random":true
	},
	
	"cuts":{
		"depositCut":false,
		"withdrawCut":true
	}	
}

The “cuts” settings indicate which AspectJ “pointcut” to turn on. The “random” setting indicates if we want the exceptions to be randomly inserted into the code base at the enabled pointcuts.

The Abstract failure injection aspect. Subclasses (aspects) will supply the actual pointcuts to specify where to ‘do’ the injection.

/**
 * FailureInjectionAspect.aj 
 * @author jbetancourt
 * 
 */

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Abstract Aspect that determines if failure should occur.
 * @author jbetancourt
 * 
 */
public abstract aspect FailureInjectionAspect {
	private Map<String, Boolean> pointcutFlags = new HashMap<String, Boolean>();
	private volatile boolean initialized =false;
	
	/** 
	 * Initialize Failure injection aspect.
	 * @throws Exception 
	 * 
	 */
	protected void init() throws Exception {
		Config config = new Config();
		config.configure();
		pointcutFlags = config.getPointcutFlags();		
		initialized = true;
	}	

	/**
	 * Get boolean value for pointcut name.
	 * 
	 * @param name pointcut name.
	 * @return true if pointcut enabled.
	 * @throws IOException 
	 */
	protected boolean isPointcutEnabled(String name) {
		if(!initialized){
			try {
				init();
			} catch (Exception e) {
				throw new IllegalStateException(
						"Could not initialize object",e);
			}
		}
		
		boolean f = false;	
		Object val = pointcutFlags.get(name);
		if (null != val) {
			f = ((Boolean) val).booleanValue();
		}	

		return f;
	}
	
} // end FailureInjectionAspect.aj

Here is a aspect that uses a nulling type of injection.

/**
 * 
 * Example of an aspect for nulling an argument to a method.
 * @author jbetancourt
 *
 */
public aspect AmountFailureAspect extends FailureInjectionAspect {

	/** fault the deposit */
	private pointcut depositCut(Long amount) :
		execution(public void BankService.deposit(Long)) 
		&& if(AmountFailureAspect.aspectOf().isPointcutEnabled("depositCut"))
		&& args(amount) 
		&& !within(FailureInjectionAspect)
	;

	/** fault the withdrawal */
	private pointcut withdrawCut(Long amount) :
		execution(public void BankService.withdraw(Long)) 
		&& if(AmountFailureAspect.aspectOf().isPointcutEnabled("withdrawCut"))
		&& args(amount) 
		&& !within(FailureInjectionAspect)
	;

	/** Null the amount arg */
	void around(Long amount) : depositCut(amount)|| withdrawCut(amount) {
		amount = null;
		proceed(amount);
	}
}

Here is how to read the configuation JSON file. I use the JSON-Simple library.

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

/**
 * 
 * @author jbetancourt
 *
 */
public class Config {
	private static final Logger logger = 
          Logger.getLogger(Config.class.getName());
	private String configFile = "\\src\\properties.json";
	private Map<String, Boolean> pointcutFlags = new HashMap<String, Boolean>();
	private volatile boolean initialized = false;
	private String basePath;

	/**
	 * 
	 * @param configFile2 
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public void configure() throws Exception {
		basePath = new File(".").getAbsolutePath();

		String path = basePath + configFile;

		Object obj = (JSONObject) JSONValue
				.parse(new FileReader(new File(path)));
		
		Map<String, Map<String, ?>> map = (Map<String, Map<String, ?>>) obj;
		pointcutFlags = (Map<String, Boolean>) map.get("cuts");
		Map<String, Object> settings = (Map<String, Object>) map
				.get("settings");
		
		Object r = settings.get("random");
		boolean randomize = (r != null && ((Boolean)r)) ;
		
		if(randomize){
			println(String.format(
			    "Pointcut usage\n%16s %6s    %6s","Name        ",
			    "Prior","Current"));
			
			for(Map.Entry<String, Boolean>entry : pointcutFlags.entrySet()){
				Boolean prior = entry.getValue();
				Boolean f = Math.random() > 0.65;
				entry.setValue(f);
				println(String.format(
					"%15s: %6s -> %6s", entry.getKey(),prior,f));
			}
			println("\n");		
		}		
		
		saveConfig();		
		initialized = true;		
		logger.log(Level.INFO,"Initialized: " + initialized);
	}
	
	/**
	 * Write the config settings to external JSON file.
	 * 
	 * Format is: { cutname : boolean , ... }
	 *   Example: {"withdrawCut":true,"depositCut":true}
	 * Will be used to set up behavior analysis service to 
	 * monitor response.
	 * 
	 * @throws IOException
	 */
	protected void saveConfig() throws IOException{
		String json = JSONValue.toJSONString(pointcutFlags);
		File file = new File(basePath + "\\runtimeProperties.json");
		FileWriter writer = new FileWriter(file);		
		writer.append(json);		
		writer.close();		
	}	

	/** getter */
	public Map<String, Boolean> getPointcutFlags() {
		return pointcutFlags;
	}

	/** setter */
	public void setPointcutFlags(Map<String, Boolean> cutFlags) {
		this.pointcutFlags = cutFlags;
	}

	/**
	 * Just a shortcut to System.out.println(String).
	 * @param s
	 */
	private void println(String s){
		System.out.println(s);
	}
}

Running at the command line

Using AspectJ is much easier in a supporting IDE like Eclipse. Below is the “mess”, unless you love the CLI, of compiling and running in a command shell. Could be made clean by creating aliases, scripts, etc.

cd src
src>javac -d ..\bin -cp ..\jars\json-simple-1.1.jar  *.java
src>java -cp ..\bin Main
Jun 9, 2011 3:18:24 PM Main main
INFO: Starting Main.....
   Deposit:  100
   Withdraw: 200
   Balance:  900

Now we change the flag from false to true in the runtimeInjection.json file:

src>type runtimeInjection.json | sed "s/false/true/" > temp
src>copy /Y temp runtimeInjection.json
src>del temp

Compile the aspects using the Aspectj “ajc” compiler.  Here we use 1.6 compliance level; destination of output to ..\bin folder; and give the classpath.

c:\Users\jbetancourt\Documents\projects\dev\AspectsForNullTesting\src&gt;\java\aspectj1.6\bin\ajc -1.6 -d ..\bin -cp "c:\java\aspectj1.6\lib\aspectjrt.
jar;c:\java\aspectj1.6\lib\aspectjtools.jar;c:\java\aspectj1.6\lib\aspectjweaver.jar;..\jars\json-simple-1.1.jar" -sourceroots .

Now we run the same Main program.  Since the pointcut flag is true, the advise is invoked and the list argument to the service(List) is set to null.

c:\Users\jbetancourt\Documents\projects\dev\AspectsForNullTesting&gt;java -cp "c:\java\aspectj1.6\lib\aspectjrt.jar;c:\java\aspectj1.6\lib\aspectjtools
.jar;c:\java\aspectj1.6\lib\aspectjweaver.jar;jars\json-simple-1.1.jar;bin;." Main
Jun 9, 2011 3:25:04 PM Main main
INFO: Starting Main.....
Pointcut usage
Name          Prior    Current
withdrawCut:   true -&gt;  false
depositCut:  false -&gt;  false
c:\Users\jbetancourt\Documents\projects\dev\AspectsForNullTesting&gt;java -cp "c:\java\aspectj1.6\lib\aspectjrt.jar;c:\java\aspectj1.6\lib\aspectjtools
.jar;c:\java\aspectj1.6\lib\aspectjweaver.jar;jars\json-simple-1.1.jar;bin;."   Main
Jun 9, 2011 3:25:10 PM Main main
INFO: Starting Main.....
Pointcut usage
Name          Prior    Current
withdrawCut:   true -&gt;   true
depositCut:  false -&gt;   true
Jun 9, 2011 3:25:10 PM Config exec
INFO: Initialized: true
Exception in thread "main" java.lang.NullPointerException
at BankService.deposit_aroundBody0(BankService.java:19)
at BankService.deposit_aroundBody1$advice(BankService.java:26)
at BankService.deposit(BankService.java:1)
at Main.main(Main.java:16)

c:\Users\jbetancourt\Documents\projects\dev\AspectsForNullTesting&gt;java -cp "c:\java\aspectj1.6\lib\aspectjrt.jar;c:\java\aspectj1.6\lib\aspectjtools
.jar;c:\java\aspectj1.6\lib\aspectjweaver.jar;jars\json-simple-1.1.jar;bin;."   Main
Jun 9, 2011 3:25:13 PM Main main
INFO: Starting Main.....
Pointcut usage
Name          Prior    Current
withdrawCut:   true -&gt;   true
depositCut:  false -&gt;  false
Jun 9, 2011 3:25:13 PM Config exec
INFO: Initialized: true
Deposit:  100
Exception in thread "main" java.lang.NullPointerException
at BankService.withdraw_aroundBody2(BankService.java:25)
at BankService.withdraw_aroundBody3$advice(BankService.java:26)
at BankService.withdraw(BankService.java:1)
at Main.main(Main.java:17)

Updates

  • Feb 1, 2012: Just learned about Byteman.

Further Reading



Nicolas Lens – Sumus Vicinae (Flamma Flamma)


Follow

Get every new post delivered to your Inbox.