Friday 22 May 2009

IE8 + AVG = Problem?

My IE8 fails to connect to any site from time to time. This happens sporadically and on certain new tabs only. After trawling through the suggestions in this discussion group, I found that the following solutions from fufufufu worked for me.
  1. Work around: if one tab does not connect, try open another one. Some tabs will eventually work.
  2. Solution: disable my AVG Anti-Virus Free (v8.5)'s Link Scanner feature (done in AVG's GUI client)
Interestingly, none of these problems with IE had ever occurred to my trusted FireFox.

Tuesday 19 May 2009

IE8 + Outlook Web Access = Problems

A couple of days ago I upgraded my old IE6 to IE8 because IE6 refused to display one of my ZK pages and spat out an error message box.

As I had to use Outlook Web Access (OWA) daily (which is the only reason why I still have IE on my machine), I ran into trouble straight away after the upgrade:

  1. Any editing screens in OWA - e.g. editing a mail was incredibly slow. This was fixed by clicking the Options view in OWA and scroll down to E-mail Security section and click Re-install button. This installed the latest S/MIME ActiveX.
  2. When downloading Office 2007 file types (docx, xlsx, pptx, etc.), OWA attempts to download them as .zip files. This was fixed by adding my OWA web site URL to the Trusted sites list in IE8 (Internet Options -> Security -> Trusted sites) as suggested here.
  3. Cannot send or reply any more! - After working for a couple of days, OWA played up again: when replying mail I got Error: ‎(0x8000ffff)‎: Catastrophic failure; when sending new mail, I got error messagebox saying access denied... Digging through Google, others have experienced the same problem but no solutions. :( The workaround is to uninstall the OWA S/MIME component (as shown in point 1 above)!
Now I know what makes dogs run around and around chasing their own tails - it's their breakfast!

Thursday 14 May 2009

Server Push + Event in ZK

I recently implemented a dashboard type of web application in ZK to display a collection of KPI metrics data using various views, for example
  1. Dashboard view - by using some flash dial/meter widgets
  2. Tree view - see screenshot below
  3. Google map view - showing geographical metrics on the map

I want to use ZK's server push feature to dynamically update the views only when the corresponding metric value has been changed and detected from the back end/server side. The examples that are available from ZK small talks invariably pass the widget(s) to be updated to the worker thread and have them updated by the server side. This approach does not quite work in my application for the following reasons:

  1. The various views (see screenshot above) are opened/closed by the user dynamically. Therefore, I don't know which widgets are visible and should be updated;
  2. There are too many widgets to be updated - there could be dozens or hundreds of metrics displayed in the view. So one approach could be to pass the whole view to the server side and have it figure out which widgets to update. I feel that the server side shouldn't be bothered with such a responsibility and the shear number/volume of the widgets involved in the view could render this infeasible.

So I took an alternative approach by combining the server push and event posting that are available in ZK framework.

The main page (main.zul file) contains the code to turn on and off server push as part of its zscript:

void startServerPush() {
 if(!desktop.isServerPushEnabled()){
     desktop.enableServerPush(true);
 }
 MetricsUpdateThread mut = new MetricsUpdateThread(user, desktop);
 mut.start();
}

void endServerPush() {
 if(desktop.isServerPushEnabled()){
     desktop.enableServerPush(false);
 }
}
The MetricsUpdateThread class is shown below:
public class MetricsUpdateThread extends Thread {
 private static final int DELAY_TIME=2000; // 2 second.
 private Desktop _desktop;
 private boolean _ceased;
 
 public MetricsUpdateThread(Desktop desktop) {
  this._desktop=desktop;
 }
 public void updateChangedMetrics() {
  HashSet<Metric> metrics=new HashSet<Metric>();
  // find all changed metrics and put them in the metrics Set
  ...
  if(metrics.size()>0)
    Events.postEvent(new Event("onMetricChanged", null, metrics));
 }
 
 public void run() {
  if (!_desktop.isServerPushEnabled())
   _desktop.enableServerPush(true);
  try {
   while (!_ceased) {
    Executions.activate(_desktop);
    try {
     updateChangedMetrics();
    } finally {
     Executions.deactivate(_desktop);
    }
    Threads.sleep(DELAY_TIME); // Update delay time
   }
  } catch (DesktopUnavailableException due) {
   //System.out.println("Browser exited.");
  } catch (InterruptedException ex) {
   //System.out.println("Server push interrupted.");
  } catch (IllegalStateException ie) {
   //System.out.println("Server push ends.");
  } finally {
   if (_desktop.isServerPushEnabled()) {
    _desktop.enableServerPush(false);
    //System.out.println("Server push disabled.");
   }
  }
 }
}

Notice the Events.postEvent() in the updateChangedMetrics() method, which broadcasts an event if there are any changed metrics. These events are then handled by the corresponding view's zscript. For example, the treeview above has the event handler at its root component like so:
...


 metrics = event.getData();
 for(Metric metric : metrics) {
  tcMovement = win.getFellowIfAny(metric.getId()+"_move");
  if(tcMovement!=null) {
   tcMovement.setImage(Util.constructMovementImage(metric));
    
   tcValue = win.getFellow(metric.getId()+"_value");
   tcValue.setLabel(metric.getValueAsString(metric.getCurrentValue()));
  }
 }

...

...
This approach of combining Server Push and Event broadcasting achieves the effect that I wanted. However, I can't help feeling that it is a bit complicated. So I wonder whether there is a better, simpler or more standard approach to achieve the same user experience in ZK.