Wednesday, August 26, 2009

Back and Forward Buttons working in RichFaces using Dojo

Recently I have been doing some work with RichFaces and encountered the biggest problem with AJAX based applications - the BACK button is not working. BTW, I cetainly recommend RichFaces, specifically its Ajax4JSF module, which make AJAX so simple. Anyways start doing some research and ultimately got working by integrating Dojo's back button support into my RichFaces application.

Basically there are 3 part of the solution:
  1. Adding the server side support to keep a history of the AJAX calls being made.
  2. Add and initialize Dojo to your web application.
  3. Send back button click events to load the previous state of the UI on the server side.
You can download the code from here.

So the first step is to create a session-scoped History bean that will maintain a queue of the states. Define 4 simple apis:
  • addToBack - adds the previous state to the history
  • addToForward - adds the current state to the history
  • doBack - go to the previous state
  • doForward - go to the state ahead
    public class HistoryBean {
private List _backHistory = new ArrayList();
private List _forwardHistory = new ArrayList();
public HistoryBean() {
super();
}
public void doBack() {
if (_backHistory.size() == 0) return;
State state = _backHistory.remove(0);
addToForward(state);
}
public void doForward() {
if (_forwardHistory.size() == 0) return;
State state = _forwardHistory.remove(0);
addToBack(state);
}
public void addToBack(State state) {
_backHistory.add(0, state);
}
public void addToForward(State state) {
_forwardHistory.add(0, state);
}
public State getCurrentState() {
if (_backHistory.size() == 0) return null;
State state = _backHistory.get(0);
return state;
}
}


Next add and intitialize the back button module from Dojo into your application web pages. You can find more information on Dojo and back button here.

    <script type="text/javascript"  src="js/dojo/dojo.js"
djConfig="preventBackButtonFix: false">
</script>

<script type="text/javascript">
// load the dojo.back package
dojo.require("dojo.back");
dojo.back.init();
</script>

Now create a state object to insert into the browser's history. The state provides 2 functions, one for back and the other for forward. Finally set the initial state when the page is first loaded.

    <script type="text/javascript">
// define a state for the back button clicks
var state = {
back: function() {
invokeBack();
},
forward: function() {
invokeForward();
}
};
// load the initial state
dojo.back.setInitialState(state);
</script>

Now add two A4J based JavaScript functions that are invoked from the state functions above. These functions will changes the state at the server side when the back or forward buttons are clicked.

    <a4j:jsFunction name="invokeBack"
action="#{history.doBack}"
reRender="__my_tabs"/>
<a4j:jsFunction name="invokeForward"
action="#{history.doForward}"
reRender="__my_tabs"/>

In these A4J javascript functions you are doing two things, first asking the server's session to switch to teh previous or next state in the queue. Secondly re-rendering the necessary components through the "reRender" attribute.

That's all you need to get the back button functioning correctly in an application built Ajax4JSF/RichFaces. I am pretty sure you can apply the same to other JSF implementation like MyFaces and JSF RI to get it to work.

You can download an example app that shows the back/forward button in action from here.

Things that you should be careful about in the server side history implementation.
  • Avoid loops in the state management. For example, when back in invoked it should call a setter that will call back into the history to add a back state.
  • Try to store objects with very small footprints in the state to conserve memory. You can also implement a FIFO model to remove very old back states.
  • Add an api like loadState() to the State interface (see sample code) that will allow you to implement the state loading in different parts of your application.

Monday, August 17, 2009

Securing methods using AOP

I am pretty sure some of us, the Java developers, have encountered this problem before. You would want to protect a particular method from illegal access. In other words no one should be able to right a Java program and be able to access this method. You in this world of software development all you code is already exposed, even though they might have published javadocs and any other form of documentation. Developers can use a decompiler to see the code and figure out how to call it. This is specifically a big problem for security related methods like encryption/decryption and password related apis.

I hope I was able to explain the problem.

Now to the solution. I used AOP (Aspect Oriented Programming) to solve the problem. AOP basically allows you to inject custom code into the compiled byte code of a class. So I take advantage of this really strong feature and implement a way to secure certain methods in the code base.

Download AspectJ from http://www.eclipse.org/aspectj/. Create an aspect that protects the said API.

    public aspect ProtectMethodAspect {

private static Map allowedRegistry = new HashMap();

static {
List allowedMethods = new ArrayList();
allowedMethods.add("com.mycomp.security.PasswordUtil");
allowedMethods.add("com.mycomp.security.UserUtil");
allowedMethods.add("com.mycomp.somepkg.SomeClass");
}

pointcut protectMethod() :
execution (* com.mycom.security.EncryptionUtil.decrypt(..));

before () : protectMethod() {

// get the caller by using the stack
try {
throw new Exception();
} catch (Exception e) {

StackTraceElement[] stack = e.getStackTrace();
String callingClass = stack[2].getClassName();

// if called within the same class, allow the call
if (callingClass.equals(thisJoinPoint.getSourceLocation()
.getWithinType().getName()))
return;

String methodName = getMethodSignature(thisJoinPoint);

// check the caller is allowed to call
List allowedClasses = allowedRegistry.get(methodName);
if (allowedClasses != null) {
// if not allowed the throw SecurityException
if (!allowedClasses.contains(callingClass)) {
throw new SecurityException("Access denied.");
}
}

}
}

public static String getMethodSignature (JoinPoint jp) {
String mSig = jp.getSignature().toString();
int ppos = mSig.indexOf("(");
String mName = mSig.substring(0, ppos);
int spos = mName.indexOf(" ");
if (spos > -1)
mName = mName.substring(spos+1);
return mName + mSig.substring(ppos);
}

}

Now weave the aspect into the compiled classes under your build directory using the Ant task "iajc". For more information on this task refer to http://www.eclipse.org/aspectj/doc/released/devguide/antTasks-iajc.html.

When you try to access the method from any class that is not allowed you will get the exception "java.lang.SecurityException: Access Denied.".

Note: I know that this looks very impressive and you must be itching to do lot of other things with AOP but be careful. The biggest drawback of AOP is that it can easily get misused and lead to serious performance problems. You should only use AOP for targeted functionality and not to solve business problems.

Friday, August 14, 2009

Synchronization: Java wait notify model using a monitor

One of the common problems that I have encountered in my coding career is synchronization bottle necks. This comes with using a Singleton design pattern. When one thread updates the objects and a second thread is trying to access the same set of objects you get into situations where there are stuck threads. You would want the second thread to wait till the first thread is finished updating the objects. The most common practice for java developers is use Java Synchronization. For example:

    private static List myObjects = new ArrayList();

public static synchronized void putObject(String object) {
synchronized(myObjects) {
myObjects.add(object);
}
}

public static String getObject(int index) {
synchronized(myObjects) {
return myObjects.get(index);
}
}

The problem with this approach is that all the calls are serialized, meaning they will wait for the previous call to complete. To explain it more, say the update takes 100 milliseconds and each get takes 10 milliseconds each, you will see the following:

    putObject()      - started at 0 ms
getObject()[1] - called at 1 ms
getObject()[2] - called at 1 ms
getObject()[3] - called at 1 ms
putObject() - completed at 100 ms
getObject()[1] - completed at 110 ms
getObject()[2] - completed at 120 ms
getObject()[3] - completed at 130 ms

Now you might say that why don't you remove the synchronized block from the getObject method. Obviously you can but that will lead to reading inconsistent data. In this case the getObject calls will not wait for the updates to complete and get the current data from the list, which might be invalid or stale. If you business requirement is fine with this situation you can most welcome to remove the synchronized block from the getObject method.

But to make to that the getObject call do wait for the putObject call to finish, I use a wait-notify model. In this model all the thread making a getObject call will wait for the updateObject call to complete and then process with the getObject call without waiting for the other getObject calls to complete. To depict it in action, here is what you would see when you run the same test above:

    putObject()      - started at 0 ms
getObject()[1] - called at 1 ms
getObject()[2] - called at 1 ms
getObject()[3] - called at 1 ms
putObject() - completed at 100 ms
getObject()[1] - completed at 110 ms
getObject()[2] - completed at 110 ms
getObject()[3] - completed at 110 ms

You must have noticed that all the getObject calls happen at the same time at 110 ms and not 10 ms apart.

So how do I achieve this? Using a simple monitor object. This object has a simple boolen "isBusy" flag which is used to control whether a thread is allowed to proceed or not. Here is the code for the monitor implementation:

    public class Monitor {

private boolean isBusy = false;

public synchronized void lock() {
// locks the monitor
while (true) {
if (isBusy) {
try {
wait();
} catch (InterruptedException e) {
// ignore
}
} else {
break;
}
}

isBusy = true;
}

public void checkLock() {
while (true) {
if (isBusy) {
synchronized(this) {
try {
wait();
} catch (InterruptedException e) {
// ignore
}
}
} else {
break;
}
}
}

public synchronized void releaseLock() {
isBusy = false;
this.notifyAll(); // this will release the lock
}

}

And this is the implementation of the putObject:

    private static Monitor monitor = new Monitor();

public static synchronized void putObject(String object) {
monitor.lock(); // this will lock the monitor
try {
myObjects.add(object);
} finally {
monitor.releaseLock(); // this will release lock on the monitor
}
}

And this is the implementation of the getObject:

    private static Monitor monitor = new Monitor();

public static String getObject(int index) {
monitor.checkLock(); // this will check for a lock on the monitor
return myObjects.get(index);
}

The notifyAll() call in the releaseLonc() methos will notify all thread waiting on the monitor that the lock has been released, which will allow all the thread to proceed with the execution at the same time.