Oct 3, 2009

PageBus Implementation using GWT-Ext

Abstract

PageBus is an Open-Source Javascript messaging bus for integrating heterogenous AJAX elements in a web page through broadcasting and listening of events published to specific topic names. This article provides the overview of PageBus and how it is implemented in GWT-ExtJS.

INTRODUCTION

PageBus

PageBus is an open-source Javascript messaging bus for integrating heterogenous AJAX elements in a web page through broadcasting and listening of events published to specific topic names. Messages can be dispatched from one AJAX component to another, or they can be bridged with messaging systems on the remote server.

Rather than hard-wiring the AJAX components on a page to talk to one another, PageBus simplifies development by providing a simple publish-subscribe API. This helps modularize applications and promotes team development, unit testing, and better source repository management.

The PageBus class can be use to publish objects to any topic and have other (decoupled) components subscribe to these topics. It is a powerful mechanism for inter component communication and state management.

Google Web Toolkit (GWT)

GWT is an open source Java software development framework that allows web developers to create and maintain complex JavaScript front-end applications in Java. Other than a few native libs, everything is Java source that can be built on any supported platform with the included GWT Ant build files.

GWT emphasizes reusable, efficient solutions to recurring Ajax challenges, namely asynchronous remote procedure calls, history management, bookmarking, and cross-browser portability.

ExtJS

Ext JS is a cross-browser JavaScript library for building rich internet applications.
• High performance, customizable UI widgets
• Well designed, documented and extensible Component model

GWT-ExtJS

Ext GWT is a Java library for building rich internet applications with GWT.
• Native GWT solution with no external JavaScript
• Full remote procedure support using GWT RPC, JSON, and XML

How does PageBus work?

PageBus uses publish and subscribe APIs to send events and messages between components rather than get bogged down in point to point integrations between components that lead to unwieldy and less manageable code.




Benefits



  • PageBus helps developers drastically simplify development by using publish and subscribe model to send messages between components rather than get stuck with point to point integrations between components that can lead to unmanageable code.
  • In addition, adherence to publish and subscribe architecture helps modularize applications into distinct pieces making team development, unit testing, and source code management easier as well.
  • In addition, using MDC, user interface components can communicate one-to-one, one-to-may or many-to-many

PageBus Methods

Publish() method

public static native void publish(String subject, Object message)



  • It is used to publish an object/message to the specific topic.
  • Argument1 contains the subject to publish the message to.
  • Argument2 contains the message to publish.

Subscribe() method

public static native Subscription subscribe(String subject, SubscriptionCallback callback)

1. Subscribe to the specified topic.
2. Argument1 contains the topic to subscribe to.
3. Argument2 is the callback to invoke when a message is received on the subscribed topic.
4. Returns the handle to the subscription which can be useful to unsubscribe to topic.

unsubscribe() method

public static native void unsubscribe(Subscription subscription)

1. Unsubscribe previous subscription
2. Argument1 contains the subscription object which needs to unsubscribed.

Sample source Code for PageBus implementation in GWT-ExtJS.

This program has two Subscriber grids and one Subscriber panel, which subscribes for PUBLISH_TOPIC. Whenever a Publish company Record is pressed it publishes PUBLISH_TOPIC. The grids and the subscriber panel would retrieve the Record object and populate the same in the grids and display the necessary information from the records object in the Subscriber panel.

1. Declare the topic to be published in the class



static String PUBLISH_TOPIC = "recordAdded";

2. Publishing the Topic, whenever the button is clicked. It publishes the message Object to pageBus.




Button btnPublish = new Button("Publish Company Record",
new ButtonListenerAdapter() {
public void onClick(Button button, EventObject e)
{
Object[] data = new Object[] {
"Company - " + (count++),
new Double(40.48),
new Double(0.51),
new Double(1.28),
"9/1 12:00am", "DD", "Manufacturing"
};
Record record = recordDef.createRecord(data);
PageBus.publish(PUBLISH_TOPIC, record);
}
});


3. Subscribing for the Topic, whenever there is any published topic matching with the subscriber in the pagebus. it retrieves the message Object using SubscriptionCallback method.




PageBus.subscribe(PubSubSample.PUBLISH_TOPIC,
new SubscriptionCallback() {
public void execute(String subject, Object message)
{
Record record = (Record) message;
getBody().update("Received Company update "
+ record.getAsString("company"));
}
});
Complete GWT-ExtJs PageBus implementation Source code



package com.samples.gwtext.client;

import com.google.gwt.core.client.EntryPoint;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.Margins;
import com.gwtext.client.core.RegionPosition;
import com.gwtext.client.data.ArrayReader;
import com.gwtext.client.data.DateFieldDef;
import com.gwtext.client.data.FieldDef;
import com.gwtext.client.data.FloatFieldDef;
import com.gwtext.client.data.MemoryProxy;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.RecordDef;
import com.gwtext.client.data.Store;
import com.gwtext.client.data.StringFieldDef;
import com.gwtext.client.pagebus.PageBus;
import com.gwtext.client.pagebus.SubscriptionCallback;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.Viewport;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.grid.ColumnConfig;
import com.gwtext.client.widgets.grid.ColumnModel;
import com.gwtext.client.widgets.grid.GridPanel;
import com.gwtext.client.widgets.layout.BorderLayout;
import com.gwtext.client.widgets.layout.BorderLayoutData;
import com.gwtext.client.widgets.layout.FitLayout;

public class PubSubSample implements EntryPoint {
private static int count = 1;
public static String PUBLISH_TOPIC = "recordAdded";

private RecordDef recordDef;

public void onModuleLoad() {
Panel mainPanel = new Panel();
mainPanel.setBorder(false);
mainPanel.setPaddings(15);
mainPanel.setLayout(new FitLayout());

recordDef = new RecordDef(new FieldDef[] {
new StringFieldDef("company"), new FloatFieldDef("price"),
new FloatFieldDef("change"), new FloatFieldDef("pctChange"),
new DateFieldDef("lastChanged", "n/j h:ia"),
new StringFieldDef("symbol"), new StringFieldDef("industry") });

SubscriberGrid sGrid1 = new SubscriberGrid();
sGrid1.setTitle("Subscriber1");
sGrid1.setHeight(200);
sGrid1.setWidth(200);

SubscriberGrid sGrid2 = new SubscriberGrid();
sGrid2.setTitle("Subscriber2");
sGrid2.setHeight(200);
sGrid2.setWidth(200);

Button btnPublish = new Button("Publish Company Record",
new ButtonListenerAdapter() {
public void onClick(Button button, EventObject e) {
Object[] data = new Object[] {
"Company - " + (count++), new Double(40.48),
new Double(0.51), new Double(1.28),
"9/1 12:00am", "DD", "Manufacturing" };
Record record = recordDef.createRecord(data);
PageBus.publish(PUBLISH_TOPIC, record);
}
});

Panel borderPanel = new Panel();
borderPanel.setLayout(new BorderLayout());

SubscriberPanel sPanel = new SubscriberPanel();
sPanel.setTitle("Subscriber Panel");
sPanel.setHeight(200);
sPanel.setWidth(300);
sPanel.setAutoScroll(true);

//South Panel contains Subscriber Panel
Panel southPanel = new Panel();
southPanel.setHeight(200);
southPanel.setCollapsible(true);
southPanel.setLayout(new FitLayout());
southPanel.add(sPanel);

BorderLayoutData southData = new BorderLayoutData(RegionPosition.SOUTH);
southData.setMinSize(100);
southData.setMaxSize(200);
southData.setMargins(new Margins(0, 0, 0, 0));
southData.setSplit(true);
borderPanel.add(southPanel, southData);

//East Panel contains the Publish Button
Panel eastPanel = new Panel();
eastPanel.setCollapsible(true);
eastPanel.setWidth(100);
eastPanel.setLayout(new FitLayout());
eastPanel.addButton(btnPublish);

BorderLayoutData eastData = new BorderLayoutData(RegionPosition.EAST);
eastData.setSplit(true);
eastData.setMinSize(175);
eastData.setMaxSize(400);
eastData.setMargins(new Margins(0, 0, 5, 0));
borderPanel.add(eastPanel, eastData);

//West Panel contains Subscriber Grid2
Panel westPanel = new Panel();
westPanel.setCollapsible(true);
westPanel.setWidth(200);
westPanel.setLayout(new FitLayout());
westPanel.add(sGrid2);

BorderLayoutData westData = new BorderLayoutData(RegionPosition.WEST);
westData.setSplit(true);
westData.setMinSize(175);
westData.setMaxSize(400);
westData.setMargins(new Margins(0, 5, 0, 0));
borderPanel.add(westPanel, westData);

//Center Panel contains Subscriber Grid1
Panel centerPanel = new Panel();
centerPanel.setLayout(new FitLayout());
centerPanel.add(sGrid1);

borderPanel.add(centerPanel,
new BorderLayoutData(RegionPosition.CENTER));

mainPanel.add(borderPanel);
Viewport viewport = new Viewport(mainPanel);
}

private class SubscriberPanel extends Panel {
public SubscriberPanel() {
PageBus.subscribe(PubSubSample.PUBLISH_TOPIC,
new SubscriptionCallback() {
public void execute(String subject, Object message) {
Record record = (Record) message;
getBody().update(
"Received Company update "
+ record.getAsString("company"));
}
});
}
}

private class SubscriberGrid extends SampleGrid {
public SubscriberGrid() {
PageBus.subscribe(PubSubSample.PUBLISH_TOPIC,
new SubscriptionCallback() {
public void execute(String subject, Object message) {
Record record = (Record) message;
store.insert(0, record);
}
});
}
}

private class SampleGrid extends GridPanel {
protected Store store;

public SampleGrid() {
RecordDef recordDef = new RecordDef(new FieldDef[] {
new StringFieldDef("company"), new FloatFieldDef("price"),
new FloatFieldDef("change"),
new FloatFieldDef("pctChange"),
new DateFieldDef("lastChanged", "n/j h:ia"),
new StringFieldDef("symbol"),
new StringFieldDef("industry") });

Object[][] data = getCompanyData();
MemoryProxy proxy = new MemoryProxy(data);

ArrayReader reader = new ArrayReader(recordDef);
store = new Store(proxy, reader);
store.load();

setStore(store);

ColumnConfig[] columns = new ColumnConfig[] {
new ColumnConfig("Company", "company", 200, true, null,
"company"), new ColumnConfig("Price", "price", 35),
new ColumnConfig("Change", "change", 45),
new ColumnConfig("% Change", "pctChange", 65),
new ColumnConfig("Last Updated", "lastChanged", 180),
new ColumnConfig("Industry", "industry", 100, true) };

ColumnModel columnModel = new ColumnModel(columns);
setColumnModel(columnModel);

setFrame(true);
setStripeRows(true);
}

private Object[][] getCompanyData() {
return new Object[][] {
new Object[] { "3m Co", new Double(71.72),
new Double(0.02), new Double(0.03), "9/1 12:00am",
"MMM", "Manufacturing" },
new Object[] { "Alcoa Inc", new Double(29.01),
new Double(0.42), new Double(1.47), "9/1 12:00am",
"AA", "Manufacturing" },
new Object[] { "Altria Group Inc", new Double(83.81),
new Double(0.28), new Double(0.34), "9/1 12:00am",
"MO", "Manufacturing" },
new Object[] { "American Express Company",
new Double(52.55), new Double(0.01),
new Double(0.02), "9/1 12:00am", "AXP", "Finance" },
new Object[] { "American International Group, Inc.",
new Double(64.13), new Double(0.31),
new Double(0.49), "9/1 12:00am", "AIG", "Services" },
new Object[] { "AT&T Inc.", new Double(31.61),
new Double(-0.48), new Double(-1.54),
"9/1 12:00am", "T", "Services" },
new Object[] { "Boeing Co.", new Double(75.43),
new Double(0.53), new Double(0.71), "9/1 12:00am",
"BA", "Manufacturing" },
new Object[] { "Caterpillar Inc.", new Double(67.27),
new Double(0.92), new Double(1.39), "9/1 12:00am",
"CAT", "Services" },
new Object[] { "Citigroup, Inc.", new Double(49.37),
new Double(0.02), new Double(0.04), "9/1 12:00am",
"C", "Finance" },
new Object[] { "E.I. du Pont de Nemours and Company",
new Double(40.48), new Double(0.51),
new Double(1.28), "9/1 12:00am", "DD",
"Manufacturing" } };
}
}
}

Output screen shots

Before Publish Company Record button is pressed







After Publish Company Record is pressed






References

http://extjs.com/

http://www.gwt-ext.com/demo/#pubsub

http://www.tibco.com/devnet/pagebus/default.jsp

1 comments:

Vina Sana said...

A wonderful wonderful primer!! You are my teacher !

Text Widget

Copyright © Vinay's Blog | Powered by Blogger

Design by | Blogger Theme by