Initial Commit of the Hyracks Admin Console

git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_dev_next@562 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-admin-console/.classpath b/hyracks-admin-console/.classpath
new file mode 100644
index 0000000..c5921a9
--- /dev/null
+++ b/hyracks-admin-console/.classpath
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/hyracks-admin-console-0.1.8-SNAPSHOT/WEB-INF/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/hyracks-admin-console-0.1.8-SNAPSHOT/WEB-INF/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="src" path="target/generated-sources/gwt"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="output" path="target/hyracks-admin-console-0.1.8-SNAPSHOT/WEB-INF/classes"/>
+</classpath>
diff --git a/hyracks-admin-console/.project b/hyracks-admin-console/.project
new file mode 100644
index 0000000..df60f9a
--- /dev/null
+++ b/hyracks-admin-console/.project
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>hyracks-admin-console</name>
+	<comment>hyracks-admin-console project</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+		<nature>com.google.gwt.eclipse.core.gwtNature</nature>
+	</natures>
+</projectDescription>
diff --git a/hyracks-admin-console/.settings/.jsdtscope b/hyracks-admin-console/.settings/.jsdtscope
new file mode 100644
index 0000000..ba3c245
--- /dev/null
+++ b/hyracks-admin-console/.settings/.jsdtscope
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+  <classpathentry kind="src" path="src/main/webapp" />
+  <classpathentry kind="con"
+    path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER" />
+  <classpathentry kind="con"
+    path="org.eclipse.wst.jsdt.launching.WebProject">
+    <attributes>
+      <attribute name="hide" value="true" />
+    </attributes>
+  </classpathentry>
+  <classpathentry kind="con"
+    path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary" />
+  <classpathentry kind="output" path="" />
+</classpath>
diff --git a/hyracks-admin-console/.settings/com.google.appengine.eclipse.core.prefs b/hyracks-admin-console/.settings/com.google.appengine.eclipse.core.prefs
new file mode 100644
index 0000000..a60576c
--- /dev/null
+++ b/hyracks-admin-console/.settings/com.google.appengine.eclipse.core.prefs
@@ -0,0 +1,3 @@
+#Thu Jun 16 10:18:26 CEST 2011
+eclipse.preferences.version=1
+filesCopiedToWebInfLib=
diff --git a/hyracks-admin-console/.settings/com.google.gdt.eclipse.core.prefs b/hyracks-admin-console/.settings/com.google.gdt.eclipse.core.prefs
new file mode 100644
index 0000000..8019224
--- /dev/null
+++ b/hyracks-admin-console/.settings/com.google.gdt.eclipse.core.prefs
@@ -0,0 +1,5 @@
+#Thu Sep 02 10:55:28 CEST 2010
+eclipse.preferences.version=1
+jarsExcludedFromWebInfLib=
+warSrcDir=src/main/webapp
+warSrcDirIsOutput=true
diff --git a/hyracks-admin-console/.settings/com.google.gwt.eclipse.core.prefs b/hyracks-admin-console/.settings/com.google.gwt.eclipse.core.prefs
new file mode 100644
index 0000000..c803c44
--- /dev/null
+++ b/hyracks-admin-console/.settings/com.google.gwt.eclipse.core.prefs
@@ -0,0 +1,5 @@
+#Thu Jun 16 11:14:17 CEST 2011
+eclipse.preferences.version=1
+entryPointModules=
+filesCopiedToWebInfLib=gwt-servlet.jar
+gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy13YXIgc3JjL21haW4vd2ViYXBwXV0+PC9leHRyYS1hcmdzPjx2bS1hcmdzPjwhW0NEQVRBWy1YbXg1MTJtXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLmNvbXBhbnkuU29tZU1vZHVsZTwvZW50cnktcG9pbnQtbW9kdWxlPjwvZ3d0LWNvbXBpbGUtc2V0dGluZ3M+
diff --git a/hyracks-admin-console/.settings/org.eclipse.jdt.core.prefs b/hyracks-admin-console/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..96e4c8c
--- /dev/null
+++ b/hyracks-admin-console/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Wed Aug 24 10:20:07 PDT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/hyracks-admin-console/.settings/org.eclipse.wst.common.component b/hyracks-admin-console/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..8b16bad
--- /dev/null
+++ b/hyracks-admin-console/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+  <wb-module deploy-name="${module}">
+    <wb-resource deploy-path="/" source-path="/src/main/webapp"/>
+    <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
+    <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/>
+    <property name="context-root" value="${module}"/>
+    <property name="java-output-path" value="/${module}/target/www/WEB-INF/classes"/>
+  </wb-module>
+</project-modules>
diff --git a/hyracks-admin-console/.settings/org.eclipse.wst.common.project.facet.core.xml b/hyracks-admin-console/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..18c1b9a
--- /dev/null
+++ b/hyracks-admin-console/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <fixed facet="wst.jsdt.web" />
+  <installed facet="java" version="1.5" />
+  <installed facet="jst.web" version="2.3" />
+  <installed facet="wst.jsdt.web" version="1.0" />
+</faceted-project>
diff --git a/hyracks-admin-console/.settings/org.eclipse.wst.jsdt.ui.superType.container b/hyracks-admin-console/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/hyracks-admin-console/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/hyracks-admin-console/.settings/org.maven.ide.eclipse.prefs b/hyracks-admin-console/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..c74c58e
--- /dev/null
+++ b/hyracks-admin-console/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Thu Sep 02 10:42:12 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/hyracks-admin-console/pom.xml b/hyracks-admin-console/pom.xml
new file mode 100644
index 0000000..ca200e5
--- /dev/null
+++ b/hyracks-admin-console/pom.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+  xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>edu.uci.ics.hyracks</groupId>
+  <artifactId>hyracks-admin-console</artifactId>
+  <packaging>war</packaging>
+  <version>0.1.8-SNAPSHOT</version>
+
+  <parent>
+    <groupId>edu.uci.ics.hyracks</groupId>
+    <artifactId>hyracks</artifactId>
+    <version>0.1.8-SNAPSHOT</version>
+  </parent>
+
+  <properties>
+    <gwtVersion>2.3.0</gwtVersion>
+    <webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.gwt</groupId>
+      <artifactId>gwt-user</artifactId>
+      <version>${gwtVersion}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.7</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.validation</groupId>
+      <artifactId>validation-api</artifactId>
+      <version>1.0.0.GA</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.validation</groupId>
+      <artifactId>validation-api</artifactId>
+      <version>1.0.0.GA</version>
+      <classifier>sources</classifier>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.googlecode.gchart</groupId>
+      <artifactId>gchart</artifactId>
+      <version>2.6</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <!-- Generate compiled stuff in the folder used for developing mode -->
+    <outputDirectory>${webappDirectory}/WEB-INF/classes</outputDirectory>
+
+    <plugins>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>gwt-maven-plugin</artifactId>
+        <version>2.3.0-1</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>compile</goal>
+              <goal>test</goal>
+              <goal>i18n</goal>
+              <goal>generateAsync</goal>
+            </goals>
+          </execution>
+        </executions>
+        <!-- Plugin configuration. There are many available options, see 
+          gwt-maven-plugin documentation at codehaus.org -->
+        <configuration>
+          <runTarget>HyracksAdminConsole.html</runTarget>
+          <hostedWebapp>${webappDirectory}</hostedWebapp>
+          <i18nMessagesBundle>edu.uci.ics.hyracks.adminconsole.client.Messages</i18nMessagesBundle>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-war-plugin</artifactId>
+        <version>2.1.1</version>
+        <executions>
+          <execution>
+            <phase>compile</phase>
+            <goals>
+              <goal>exploded</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <webappDirectory>${webappDirectory}</webappDirectory>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.3.2</version>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/HyracksAdminConsole.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/HyracksAdminConsole.java
new file mode 100644
index 0000000..587a8a4
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/HyracksAdminConsole.java
@@ -0,0 +1,67 @@
+package edu.uci.ics.hyracks.adminconsole.client;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.DockLayoutPanel;
+import com.google.gwt.user.client.ui.RootLayoutPanel;
+
+import edu.uci.ics.hyracks.adminconsole.client.connection.ServerConnection;
+import edu.uci.ics.hyracks.adminconsole.client.panels.ApplicationsPanel;
+import edu.uci.ics.hyracks.adminconsole.client.panels.DashboardPanel;
+import edu.uci.ics.hyracks.adminconsole.client.panels.JobsPanel;
+import edu.uci.ics.hyracks.adminconsole.client.panels.NodeControllersPanel;
+import edu.uci.ics.hyracks.adminconsole.client.panels.TopPanel;
+
+public class HyracksAdminConsole implements EntryPoint {
+    public static HyracksAdminConsole INSTANCE;
+
+    private final Messages messages = GWT.create(Messages.class);
+
+    private ServerConnection serverConnection;
+
+    @UiField
+    TopPanel topPanel;
+
+    @UiField
+    DashboardPanel dashboardPanel;
+
+    @UiField
+    ApplicationsPanel applicationsPanel;
+
+    @UiField
+    NodeControllersPanel nodeControllersPanel;
+
+    @UiField
+    JobsPanel jobsPanel;
+
+    interface Binder extends UiBinder<DockLayoutPanel, HyracksAdminConsole> {
+    }
+
+    private final static Binder binder = GWT.create(Binder.class);
+
+    public ServerConnection getServerConnection() {
+        return serverConnection;
+    }
+
+    public void onModuleLoad() {
+        INSTANCE = this;
+        serverConnection = new ServerConnection();
+        String serverURLPrefix = Window.Location.getParameter("cclocation");
+        serverConnection.setServerURLPrefix(serverURLPrefix);
+
+        DockLayoutPanel lp = binder.createAndBindUi(this);
+
+        // Get rid of scrollbars, and clear out the window's built-in margin,
+        // because we want to take advantage of the entire client area.
+        Window.enableScrolling(false);
+        Window.setMargin("0px");
+
+        // Add the outer panel to the RootLayoutPanel, so that it will be
+        // displayed.
+        RootLayoutPanel root = RootLayoutPanel.get();
+        root.add(lp);
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/HyracksAdminConsole.ui.xml b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/HyracksAdminConsole.ui.xml
new file mode 100644
index 0000000..929e1de
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/HyracksAdminConsole.ui.xml
@@ -0,0 +1,44 @@
+<!DOCTYPE ui:UiBinder
+  SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"
+>
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+  xmlns:g='urn:import:com.google.gwt.user.client.ui'
+  xmlns:hac.panels='urn:import:edu.uci.ics.hyracks.adminconsole.client.panels'>
+
+  <g:DockLayoutPanel unit='EM'>
+    <g:north size='5'>
+      <hac.panels:TopPanel ui:field='topPanel' />
+    </g:north>
+
+    <g:center>
+      <g:TabLayoutPanel barUnit="EM" barHeight="2">
+        <g:tab>
+          <g:header>
+            Dashboard
+          </g:header>
+          <hac.panels:DashboardPanel ui:field='dashboardPanel' />
+        </g:tab>
+        <g:tab>
+          <g:header>
+            Applications
+          </g:header>
+          <hac.panels:ApplicationsPanel ui:field='applicationsPanel' />
+        </g:tab>
+        <g:tab>
+          <g:header>
+            Node Controllers
+          </g:header>
+          <hac.panels:NodeControllersPanel ui:field='nodeControllersPanel' />
+        </g:tab>
+        <g:tab>
+          <g:header>
+            Jobs
+          </g:header>
+          <hac.panels:JobsPanel ui:field='jobsPanel' />
+        </g:tab>
+      </g:TabLayoutPanel>
+    </g:center>
+  </g:DockLayoutPanel>
+
+</ui:UiBinder>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/beans/JobSummary.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/beans/JobSummary.java
new file mode 100644
index 0000000..d7af7f7
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/beans/JobSummary.java
@@ -0,0 +1,46 @@
+package edu.uci.ics.hyracks.adminconsole.client.beans;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.view.client.ProvidesKey;
+
+public final class JobSummary extends JavaScriptObject {
+    public static final ProvidesKey<JobSummary> KEY_PROVIDER = new ProvidesKey<JobSummary>() {
+        @Override
+        public Object getKey(JobSummary item) {
+            return item.getJobId();
+        }
+    };
+
+    protected JobSummary() {
+    }
+
+    public native String getJobId()
+    /*-{
+         return this["job-id"];
+    }-*/;
+
+    public native String getApplicationName()
+    /*-{
+         return this["application-name"];
+    }-*/;
+
+    public native String getStatus()
+    /*-{
+         return this.status;
+    }-*/;
+
+    public native Long getCreateTime()
+    /*-{
+         return this["create-time"];
+    }-*/;
+
+    public native Long getStartTime()
+    /*-{
+         return this["start-time"];
+    }-*/;
+
+    public native Long getEndTime()
+    /*-{
+         return this["end-time"];
+    }-*/;
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/beans/NodeDetails.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/beans/NodeDetails.java
new file mode 100644
index 0000000..d04c02c
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/beans/NodeDetails.java
@@ -0,0 +1,101 @@
+package edu.uci.ics.hyracks.adminconsole.client.beans;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArrayInteger;
+import com.google.gwt.core.client.JsArrayNumber;
+
+public final class NodeDetails extends JavaScriptObject {
+    protected NodeDetails() {
+
+    }
+
+    public native String getNodeId()
+    /*-{
+         return this["node-id"];
+    }-*/;
+
+    public native String getOSName()
+    /*-{
+         return this["os-name"];
+    }-*/;
+
+    public native String getArch()
+    /*-{
+         return this["arch"];
+    }-*/;
+
+    public native String getOSVersion()
+    /*-{
+         return this["os-version"];
+    }-*/;
+
+    public native int getNProcessors()
+    /*-{
+         return this["num-processors"];
+    }-*/;
+
+    public native int getRRDPtr()
+    /*-{
+         return this["rrd-ptr"];
+    }-*/;
+
+    public native JsArrayNumber getHeartbeatTimes()
+    /*-{
+         return this["heartbeat-times"];
+    }-*/;
+
+    public native JsArrayNumber getHeapInitSizes()
+    /*-{
+         return this["heap-init-sizes"];
+    }-*/;
+
+    public native JsArrayNumber getHeapUsedSizes()
+    /*-{
+         return this["heap-used-sizes"];
+    }-*/;
+
+    public native JsArrayNumber getHeapCommittedSizes()
+    /*-{
+         return this["heap-committed-sizes"];
+    }-*/;
+
+    public native JsArrayNumber getHeapMaxSizes()
+    /*-{
+         return this["heap-max-sizes"];
+    }-*/;
+
+    public native JsArrayNumber getNonHeapInitSizes()
+    /*-{
+         return this["nonheap-init-sizes"];
+    }-*/;
+
+    public native JsArrayNumber getNonHeapUsedSizes()
+    /*-{
+         return this["nonheap-used-sizes"];
+    }-*/;
+
+    public native JsArrayNumber getNonHeapCommittedSizes()
+    /*-{
+         return this["nonheap-committed-sizes"];
+    }-*/;
+
+    public native JsArrayNumber getNonHeapMaxSizes()
+    /*-{
+         return this["nonheap-max-sizes"];
+    }-*/;
+
+    public native JsArrayInteger getThreadCounts()
+    /*-{
+         return this["thread-counts"];
+    }-*/;
+
+    public native JsArrayInteger getPeakThreadCounts()
+    /*-{
+         return this["peak-thread-counts"];
+    }-*/;
+
+    public native JsArrayNumber getSystemLoadAverages()
+    /*-{
+         return this["system-load-averages"];
+    }-*/;
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/beans/NodeSummary.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/beans/NodeSummary.java
new file mode 100644
index 0000000..1ee5e85
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/beans/NodeSummary.java
@@ -0,0 +1,37 @@
+package edu.uci.ics.hyracks.adminconsole.client.beans;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArray;
+import com.google.gwt.view.client.ProvidesKey;
+
+public final class NodeSummary extends JavaScriptObject {
+    public static final ProvidesKey<NodeSummary> KEY_PROVIDER = new ProvidesKey<NodeSummary>() {
+        @Override
+        public Object getKey(NodeSummary item) {
+            return item.getNodeId();
+        }
+    };
+
+    protected NodeSummary() {
+    }
+
+    public native String getNodeId()
+    /*-{
+         return this["node-id"];
+    }-*/;
+
+    public native Double getSystemLoadAverage()
+    /*-{
+         return this["system-load-average"];
+    }-*/;
+
+    public native Long getHeapUsed()
+    /*-{
+         return this["heap-used"];
+    }-*/;
+
+    public static native JsArray<NodeSummary> parseNodeSummariesResult(String json)
+    /*-{
+        return eval(json)[0].result;
+     }-*/;
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/connection/ServerConnection.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/connection/ServerConnection.java
new file mode 100644
index 0000000..0d147c6
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/connection/ServerConnection.java
@@ -0,0 +1,16 @@
+package edu.uci.ics.hyracks.adminconsole.client.connection;
+
+public class ServerConnection {
+    private String serverURLPrefix;
+
+    public ServerConnection() {
+    }
+
+    public String getServerURLPrefix() {
+        return serverURLPrefix;
+    }
+
+    public void setServerURLPrefix(String serverURLPrefix) {
+        this.serverURLPrefix = serverURLPrefix;
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/details/node/charts/MemoryUsageChart.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/details/node/charts/MemoryUsageChart.java
new file mode 100644
index 0000000..dbc670f
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/details/node/charts/MemoryUsageChart.java
@@ -0,0 +1,51 @@
+package edu.uci.ics.hyracks.adminconsole.client.details.node.charts;
+
+import com.google.gwt.core.client.JsArrayNumber;
+import com.googlecode.gchart.client.GChart;
+
+public class MemoryUsageChart extends GChart {
+    private String prefix;
+
+    public MemoryUsageChart() {
+        setChartSize(720, 200);
+        setPadding("30px");
+    }
+
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+    }
+
+    public void reset(int rrdPtr, JsArrayNumber times, JsArrayNumber initSizes, JsArrayNumber usedSizes,
+            JsArrayNumber committedSizes, JsArrayNumber maxSizes) {
+        clearCurves();
+        addCurve();
+        getCurve().setLegendLabel(prefix + " Initial Size");
+        getCurve().getSymbol().setWidth(0);
+        getCurve().getSymbol().setHeight(0);
+        getCurve().getSymbol().setSymbolType(SymbolType.LINE);
+        addCurve();
+        getCurve().setLegendLabel(prefix + " Used Size");
+        getCurve().getSymbol().setWidth(0);
+        getCurve().getSymbol().setHeight(0);
+        getCurve().getSymbol().setSymbolType(SymbolType.LINE);
+        addCurve();
+        getCurve().setLegendLabel(prefix + " Committed Size");
+        getCurve().getSymbol().setWidth(0);
+        getCurve().getSymbol().setHeight(0);
+        getCurve().getSymbol().setSymbolType(SymbolType.LINE);
+        addCurve();
+        getCurve().setLegendLabel(prefix + " Maximum Size");
+        getCurve().getSymbol().setWidth(0);
+        getCurve().getSymbol().setHeight(0);
+        getCurve().getSymbol().setSymbolType(SymbolType.LINE);
+        int ptr = rrdPtr;
+        for (int i = 0; i < times.length(); ++i) {
+            getCurve(0).addPoint(i, initSizes.get(ptr));
+            getCurve(1).addPoint(i, usedSizes.get(ptr));
+            getCurve(2).addPoint(i, committedSizes.get(ptr));
+            getCurve(3).addPoint(i, maxSizes.get(ptr));
+            ptr = (ptr + 1) % times.length();
+        }
+        update();
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/details/node/charts/SystemLoadAverageChart.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/details/node/charts/SystemLoadAverageChart.java
new file mode 100644
index 0000000..21faf21
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/details/node/charts/SystemLoadAverageChart.java
@@ -0,0 +1,26 @@
+package edu.uci.ics.hyracks.adminconsole.client.details.node.charts;
+
+import com.google.gwt.core.client.JsArrayNumber;
+import com.googlecode.gchart.client.GChart;
+
+public class SystemLoadAverageChart extends GChart {
+    public SystemLoadAverageChart() {
+        setChartSize(720, 200);
+        setPadding("30px");
+    }
+
+    public void reset(int rrdPtr, JsArrayNumber times, JsArrayNumber systemLoadAverages) {
+        clearCurves();
+        addCurve();
+        getCurve().setLegendLabel("System Load Average");
+        getCurve().getSymbol().setWidth(0);
+        getCurve().getSymbol().setHeight(0);
+        getCurve().getSymbol().setSymbolType(SymbolType.LINE);
+        int ptr = rrdPtr;
+        for (int i = 0; i < times.length(); ++i) {
+            getCurve().addPoint(i, systemLoadAverages.get(ptr));
+            ptr = (ptr + 1) % times.length();
+        }
+        update();
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/details/node/charts/ThreadCountChart.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/details/node/charts/ThreadCountChart.java
new file mode 100644
index 0000000..77b6b8c
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/details/node/charts/ThreadCountChart.java
@@ -0,0 +1,33 @@
+package edu.uci.ics.hyracks.adminconsole.client.details.node.charts;
+
+import com.google.gwt.core.client.JsArrayInteger;
+import com.google.gwt.core.client.JsArrayNumber;
+import com.googlecode.gchart.client.GChart;
+
+public class ThreadCountChart extends GChart {
+    public ThreadCountChart() {
+        setChartSize(720, 200);
+        setPadding("30px");
+    }
+
+    public void reset(int rrdPtr, JsArrayNumber times, JsArrayInteger threadCounts, JsArrayInteger peakThreadCounts) {
+        clearCurves();
+        addCurve();
+        getCurve().setLegendLabel("Thread Count");
+        getCurve().getSymbol().setWidth(0);
+        getCurve().getSymbol().setHeight(0);
+        getCurve().getSymbol().setSymbolType(SymbolType.LINE);
+        addCurve();
+        getCurve().setLegendLabel("Peak Thread Count");
+        getCurve().getSymbol().setWidth(0);
+        getCurve().getSymbol().setHeight(0);
+        getCurve().getSymbol().setSymbolType(SymbolType.LINE);
+        int ptr = rrdPtr;
+        for (int i = 0; i < times.length(); ++i) {
+            getCurve(0).addPoint(i, threadCounts.get(ptr));
+            getCurve(1).addPoint(i, peakThreadCounts.get(ptr));
+            ptr = (ptr + 1) % times.length();
+        }
+        update();
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/ApplicationsPanel.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/ApplicationsPanel.java
new file mode 100644
index 0000000..f25ea7f
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/ApplicationsPanel.java
@@ -0,0 +1,17 @@
+package edu.uci.ics.hyracks.adminconsole.client.panels;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.Widget;
+
+public class ApplicationsPanel extends Composite {
+    interface Binder extends UiBinder<Widget, ApplicationsPanel> {
+    }
+
+    private final static Binder binder = GWT.create(Binder.class);
+
+    public ApplicationsPanel() {
+        initWidget(binder.createAndBindUi(this));
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/ApplicationsPanel.ui.xml b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/ApplicationsPanel.ui.xml
new file mode 100644
index 0000000..74669b0
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/ApplicationsPanel.ui.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE ui:UiBinder
+  SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"
+>
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+  xmlns:g='urn:import:com.google.gwt.user.client.ui'
+  xmlns:hac.panels='urn:import:edu.uci.ics.hyracks.adminconsole.client.panels'>
+  <g:HTML></g:HTML>
+</ui:UiBinder>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/DashboardPanel.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/DashboardPanel.java
new file mode 100644
index 0000000..6917090
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/DashboardPanel.java
@@ -0,0 +1,17 @@
+package edu.uci.ics.hyracks.adminconsole.client.panels;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.Widget;
+
+public class DashboardPanel extends Composite {
+    interface Binder extends UiBinder<Widget, DashboardPanel> {
+    }
+
+    private final static Binder binder = GWT.create(Binder.class);
+
+    public DashboardPanel() {
+        initWidget(binder.createAndBindUi(this));
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/DashboardPanel.ui.xml b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/DashboardPanel.ui.xml
new file mode 100644
index 0000000..74669b0
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/DashboardPanel.ui.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE ui:UiBinder
+  SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"
+>
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+  xmlns:g='urn:import:com.google.gwt.user.client.ui'
+  xmlns:hac.panels='urn:import:edu.uci.ics.hyracks.adminconsole.client.panels'>
+  <g:HTML></g:HTML>
+</ui:UiBinder>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/JobsPanel.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/JobsPanel.java
new file mode 100644
index 0000000..c8350dc
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/JobsPanel.java
@@ -0,0 +1,82 @@
+package edu.uci.ics.hyracks.adminconsole.client.panels;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JsArray;
+import com.google.gwt.http.client.RequestException;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.SplitLayoutPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.view.client.AsyncDataProvider;
+
+import edu.uci.ics.hyracks.adminconsole.client.beans.JobSummary;
+import edu.uci.ics.hyracks.adminconsole.client.rest.AbstractRestFunction;
+import edu.uci.ics.hyracks.adminconsole.client.rest.GetJobSummariesFunction;
+import edu.uci.ics.hyracks.adminconsole.client.widgets.JobsTableWidget;
+
+public class JobsPanel extends Composite implements JobsTableWidget.IRefreshRequestHandler {
+    interface Binder extends UiBinder<Widget, JobsPanel> {
+    }
+
+    private final static Binder binder = GWT.create(Binder.class);
+
+    @UiField
+    SplitLayoutPanel split;
+
+    @UiField
+    JobsTableWidget jobs;
+
+    @UiField
+    Widget details;
+
+    private int callCounter;
+
+    public JobsPanel() {
+        initWidget(binder.createAndBindUi(this));
+
+        jobs.setRefreshRequestHandler(this);
+
+        Timer timer = new Timer() {
+            @Override
+            public void run() {
+                refresh();
+            }
+        };
+        refresh();
+        timer.scheduleRepeating(5000);
+    }
+
+    @Override
+    public void refresh() {
+        try {
+            final int counter = ++callCounter;
+            GetJobSummariesFunction.INSTANCE.call(new AbstractRestFunction.ResultCallback<JsArray<JobSummary>>() {
+                @Override
+                public void onSuccess(JsArray<JobSummary> result) {
+                    if (counter == callCounter) {
+                        AsyncDataProvider<JobSummary> dataProvider = jobs.getDataProvider();
+                        List<JobSummary> data = new ArrayList<JobSummary>();
+                        for (int i = 0; i < result.length(); ++i) {
+                            data.add(result.get(i));
+                        }
+                        dataProvider.updateRowData(0, data);
+                        dataProvider.updateRowCount(result.length(), true);
+                    }
+                }
+
+                @Override
+                public void onError(Throwable exception) {
+
+                }
+            });
+        } catch (RequestException e) {
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/JobsPanel.ui.xml b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/JobsPanel.ui.xml
new file mode 100644
index 0000000..c12640f
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/JobsPanel.ui.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE ui:UiBinder
+  SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"
+>
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+  xmlns:g='urn:import:com.google.gwt.user.client.ui'
+  xmlns:widgets='urn:import:edu.uci.ics.hyracks.adminconsole.client.widgets'>
+  <g:SplitLayoutPanel ui:field="split">
+    <g:north size="300">
+      <g:ScrollPanel>
+        <widgets:JobsTableWidget ui:field="jobs" width="100%" height="300px"></widgets:JobsTableWidget>
+      </g:ScrollPanel>    
+    </g:north>
+    <g:center>
+      <g:HTML ui:field="details"></g:HTML>
+    </g:center>
+  </g:SplitLayoutPanel>
+</ui:UiBinder>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllerDetailsPanel.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllerDetailsPanel.java
new file mode 100644
index 0000000..bbc08d4
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllerDetailsPanel.java
@@ -0,0 +1,91 @@
+package edu.uci.ics.hyracks.adminconsole.client.panels;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.http.client.RequestException;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.Widget;
+
+import edu.uci.ics.hyracks.adminconsole.client.beans.NodeDetails;
+import edu.uci.ics.hyracks.adminconsole.client.details.node.charts.MemoryUsageChart;
+import edu.uci.ics.hyracks.adminconsole.client.details.node.charts.SystemLoadAverageChart;
+import edu.uci.ics.hyracks.adminconsole.client.details.node.charts.ThreadCountChart;
+import edu.uci.ics.hyracks.adminconsole.client.rest.AbstractRestFunction;
+import edu.uci.ics.hyracks.adminconsole.client.rest.GetNodeDetailsFunction;
+
+public class NodeControllerDetailsPanel extends Composite {
+    interface Binder extends UiBinder<Widget, NodeControllerDetailsPanel> {
+    }
+
+    private final static Binder binder = GWT.create(Binder.class);
+
+    private final String nodeId;
+
+    @UiField
+    MemoryUsageChart heapUsage;
+
+    @UiField
+    MemoryUsageChart nonheapUsage;
+
+    @UiField
+    SystemLoadAverageChart loadAverage;
+
+    @UiField
+    ThreadCountChart threadCount;
+
+    private int callCounter;
+
+    private Timer timer;
+
+    public NodeControllerDetailsPanel(String nodeId) {
+        initWidget(binder.createAndBindUi(this));
+
+        this.nodeId = nodeId;
+        heapUsage.setPrefix("Heap ");
+        nonheapUsage.setPrefix("Non-Heap ");
+
+        timer = new Timer() {
+            @Override
+            public void run() {
+                refresh();
+            }
+        };
+        refresh();
+        timer.scheduleRepeating(10000);
+    }
+
+    public void destroy() {
+        timer.cancel();
+    }
+
+    private void refresh() {
+        try {
+            final int counter = ++callCounter;
+            new GetNodeDetailsFunction(nodeId).call(new AbstractRestFunction.ResultCallback<NodeDetails>() {
+                @Override
+                public void onSuccess(NodeDetails result) {
+                    if (counter == callCounter) {
+                        loadAverage.reset(result.getRRDPtr(), result.getHeartbeatTimes(),
+                                result.getSystemLoadAverages());
+                        heapUsage.reset(result.getRRDPtr(), result.getHeartbeatTimes(), result.getHeapInitSizes(),
+                                result.getHeapUsedSizes(), result.getHeapCommittedSizes(), result.getHeapMaxSizes());
+                        nonheapUsage.reset(result.getRRDPtr(), result.getHeartbeatTimes(),
+                                result.getNonHeapInitSizes(), result.getNonHeapUsedSizes(),
+                                result.getNonHeapCommittedSizes(), result.getNonHeapMaxSizes());
+                        threadCount.reset(result.getRRDPtr(), result.getHeartbeatTimes(), result.getThreadCounts(),
+                                result.getPeakThreadCounts());
+                    }
+                }
+
+                @Override
+                public void onError(Throwable exception) {
+
+                }
+            });
+        } catch (RequestException e) {
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllerDetailsPanel.ui.xml b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllerDetailsPanel.ui.xml
new file mode 100644
index 0000000..4506f2b
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllerDetailsPanel.ui.xml
@@ -0,0 +1,37 @@
+<!DOCTYPE ui:UiBinder
+  SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"
+>
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+  xmlns:g='urn:import:com.google.gwt.user.client.ui'
+  xmlns:charts='urn:import:edu.uci.ics.hyracks.adminconsole.client.details.node.charts'>
+  <g:StackLayoutPanel unit="EM">
+    <g:stack>
+      <g:header size="2">
+        System Load
+      </g:header>
+      <g:ScrollPanel>
+        <charts:SystemLoadAverageChart ui:field="loadAverage"/>
+      </g:ScrollPanel>
+    </g:stack>
+    <g:stack>
+      <g:header size="2">
+        Memory Usage
+      </g:header>
+      <g:ScrollPanel>
+        <g:FlowPanel>
+          <charts:MemoryUsageChart ui:field="heapUsage"/>
+          <charts:MemoryUsageChart ui:field="nonheapUsage"/>
+        </g:FlowPanel>
+      </g:ScrollPanel>
+    </g:stack>
+    <g:stack>
+      <g:header size="2">
+        Thread Count
+      </g:header>
+      <g:ScrollPanel>
+        <charts:ThreadCountChart ui:field="threadCount"/>
+      </g:ScrollPanel>
+    </g:stack>
+  </g:StackLayoutPanel>
+</ui:UiBinder>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllersPanel.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllersPanel.java
new file mode 100644
index 0000000..6110d17
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllersPanel.java
@@ -0,0 +1,92 @@
+package edu.uci.ics.hyracks.adminconsole.client.panels;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JsArray;
+import com.google.gwt.http.client.RequestException;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.SplitLayoutPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.view.client.AsyncDataProvider;
+
+import edu.uci.ics.hyracks.adminconsole.client.beans.NodeSummary;
+import edu.uci.ics.hyracks.adminconsole.client.rest.AbstractRestFunction;
+import edu.uci.ics.hyracks.adminconsole.client.rest.GetNodeSummariesFunction;
+import edu.uci.ics.hyracks.adminconsole.client.widgets.NodesTableWidget;
+
+public class NodeControllersPanel extends Composite implements NodesTableWidget.IRefreshRequestHandler {
+    interface Binder extends UiBinder<Widget, NodeControllersPanel> {
+    }
+
+    private final static Binder binder = GWT.create(Binder.class);
+
+    @UiField
+    SplitLayoutPanel split;
+
+    @UiField
+    NodesTableWidget nodes;
+
+    @UiField
+    Widget details;
+
+    private int callCounter;
+
+    public NodeControllersPanel() {
+        initWidget(binder.createAndBindUi(this));
+
+        nodes.setRefreshRequestHandler(this);
+        nodes.setClickListener(new NodesTableWidget.IClickListener() {
+            @Override
+            public void click(String nodeId) {
+                if (details instanceof NodeControllerDetailsPanel) {
+                    ((NodeControllerDetailsPanel) details).destroy();
+                }
+                split.remove(details);
+                details = new NodeControllerDetailsPanel(nodeId);
+                split.add(details);
+            }
+        });
+
+        Timer timer = new Timer() {
+            @Override
+            public void run() {
+                refresh();
+            }
+        };
+        refresh();
+        timer.scheduleRepeating(10000);
+    }
+
+    @Override
+    public void refresh() {
+        try {
+            final int counter = ++callCounter;
+            GetNodeSummariesFunction.INSTANCE.call(new AbstractRestFunction.ResultCallback<JsArray<NodeSummary>>() {
+                @Override
+                public void onSuccess(JsArray<NodeSummary> result) {
+                    if (counter == callCounter) {
+                        AsyncDataProvider<NodeSummary> dataProvider = nodes.getDataProvider();
+                        List<NodeSummary> data = new ArrayList<NodeSummary>();
+                        for (int i = 0; i < result.length(); ++i) {
+                            data.add(result.get(i));
+                        }
+                        dataProvider.updateRowData(0, data);
+                        dataProvider.updateRowCount(result.length(), true);
+                    }
+                }
+
+                @Override
+                public void onError(Throwable exception) {
+
+                }
+            });
+        } catch (RequestException e) {
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllersPanel.ui.xml b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllersPanel.ui.xml
new file mode 100644
index 0000000..80b4148
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/NodeControllersPanel.ui.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE ui:UiBinder
+  SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"
+>
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+  xmlns:g='urn:import:com.google.gwt.user.client.ui'
+  xmlns:widgets='urn:import:edu.uci.ics.hyracks.adminconsole.client.widgets'>
+  <g:SplitLayoutPanel ui:field="split">
+    <g:west size="300">
+      <g:ScrollPanel>
+        <widgets:NodesTableWidget ui:field="nodes" width="100%"></widgets:NodesTableWidget>
+      </g:ScrollPanel>    
+    </g:west>
+    <g:center>
+      <g:HTML ui:field="details"></g:HTML>
+    </g:center>
+  </g:SplitLayoutPanel>
+</ui:UiBinder>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/TopPanel.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/TopPanel.java
new file mode 100644
index 0000000..a849615
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/TopPanel.java
@@ -0,0 +1,17 @@
+package edu.uci.ics.hyracks.adminconsole.client.panels;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.Widget;
+
+public class TopPanel extends Composite {
+    interface Binder extends UiBinder<Widget, TopPanel> {
+    }
+
+    private final static Binder binder = GWT.create(Binder.class);
+
+    public TopPanel() {
+        initWidget(binder.createAndBindUi(this));
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/TopPanel.ui.xml b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/TopPanel.ui.xml
new file mode 100644
index 0000000..71c7b24
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/panels/TopPanel.ui.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE ui:UiBinder
+  SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"
+>
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+  xmlns:g='urn:import:com.google.gwt.user.client.ui'
+  xmlns:mail='urn:import:com.google.gwt.sample.mail.client'>
+
+  <ui:style>
+
+  </ui:style>
+
+  <g:HTMLPanel>
+  </g:HTMLPanel>
+</ui:UiBinder>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/AbstractRestFunction.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/AbstractRestFunction.java
new file mode 100644
index 0000000..6297fd2
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/AbstractRestFunction.java
@@ -0,0 +1,47 @@
+package edu.uci.ics.hyracks.adminconsole.client.rest;
+
+import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.RequestBuilder;
+import com.google.gwt.http.client.RequestCallback;
+import com.google.gwt.http.client.RequestException;
+import com.google.gwt.http.client.Response;
+import com.google.gwt.http.client.URL;
+
+import edu.uci.ics.hyracks.adminconsole.client.HyracksAdminConsole;
+
+public abstract class AbstractRestFunction<T> {
+    protected abstract void appendURLPath(StringBuilder buffer);
+
+    protected native T packageResults(String result)
+    /*-{
+        return eval("[" + result + "]")[0].result;
+    }-*/;
+
+    public interface ResultCallback<T> {
+        public void onSuccess(T result);
+
+        public void onError(Throwable exception);
+    }
+
+    public void call(final ResultCallback<T> callback) throws RequestException {
+        StringBuilder buffer = new StringBuilder();
+        buffer.append(HyracksAdminConsole.INSTANCE.getServerConnection().getServerURLPrefix());
+        buffer.append("/rest");
+        appendURLPath(buffer);
+        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(buffer.toString()));
+
+        builder.sendRequest(null, new RequestCallback() {
+            public void onError(Request request, Throwable exception) {
+                callback.onError(exception);
+            }
+
+            public void onResponseReceived(Request request, Response response) {
+                if (200 == response.getStatusCode()) {
+                    callback.onSuccess(packageResults(response.getText()));
+                } else {
+                    callback.onError(null);
+                }
+            }
+        });
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/GetJobSummariesFunction.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/GetJobSummariesFunction.java
new file mode 100644
index 0000000..e96bc22
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/GetJobSummariesFunction.java
@@ -0,0 +1,17 @@
+package edu.uci.ics.hyracks.adminconsole.client.rest;
+
+import com.google.gwt.core.client.JsArray;
+
+import edu.uci.ics.hyracks.adminconsole.client.beans.JobSummary;
+
+public class GetJobSummariesFunction extends AbstractRestFunction<JsArray<JobSummary>> {
+    public static final GetJobSummariesFunction INSTANCE = new GetJobSummariesFunction();
+
+    private GetJobSummariesFunction() {
+    }
+
+    @Override
+    protected void appendURLPath(StringBuilder buffer) {
+        buffer.append("/jobs");
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/GetNodeDetailsFunction.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/GetNodeDetailsFunction.java
new file mode 100644
index 0000000..b535ffc
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/GetNodeDetailsFunction.java
@@ -0,0 +1,16 @@
+package edu.uci.ics.hyracks.adminconsole.client.rest;
+
+import edu.uci.ics.hyracks.adminconsole.client.beans.NodeDetails;
+
+public class GetNodeDetailsFunction extends AbstractRestFunction<NodeDetails> {
+    private String nodeId;
+
+    public GetNodeDetailsFunction(String nodeId) {
+        this.nodeId = nodeId;
+    }
+
+    @Override
+    protected void appendURLPath(StringBuilder buffer) {
+        buffer.append("/nodes/").append(nodeId);
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/GetNodeSummariesFunction.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/GetNodeSummariesFunction.java
new file mode 100644
index 0000000..6af5a01
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/rest/GetNodeSummariesFunction.java
@@ -0,0 +1,17 @@
+package edu.uci.ics.hyracks.adminconsole.client.rest;
+
+import com.google.gwt.core.client.JsArray;
+
+import edu.uci.ics.hyracks.adminconsole.client.beans.NodeSummary;
+
+public class GetNodeSummariesFunction extends AbstractRestFunction<JsArray<NodeSummary>> {
+    public static final GetNodeSummariesFunction INSTANCE = new GetNodeSummariesFunction();
+
+    private GetNodeSummariesFunction() {
+    }
+
+    @Override
+    protected void appendURLPath(StringBuilder buffer) {
+        buffer.append("/nodes");
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/JobsTableWidget.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/JobsTableWidget.java
new file mode 100644
index 0000000..4e49bba
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/JobsTableWidget.java
@@ -0,0 +1,118 @@
+package edu.uci.ics.hyracks.adminconsole.client.widgets;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.cellview.client.CellTable;
+import com.google.gwt.user.cellview.client.TextColumn;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.view.client.AsyncDataProvider;
+import com.google.gwt.view.client.HasData;
+
+import edu.uci.ics.hyracks.adminconsole.client.beans.JobSummary;
+
+public class JobsTableWidget extends Composite {
+    public interface IRefreshRequestHandler {
+        public void refresh();
+    }
+
+    interface Binder extends UiBinder<Widget, JobsTableWidget> {
+    }
+
+    private final static Binder binder = GWT.create(Binder.class);
+
+    @UiField
+    CellTable<JobSummary> table;
+
+    private AsyncDataProvider<JobSummary> jobSummaryProvider;
+
+    private IRefreshRequestHandler refreshRequestHandler;
+
+    public JobsTableWidget() {
+        initWidget(binder.createAndBindUi(this));
+
+        TextColumn<JobSummary> idCol = new TextColumn<JobSummary>() {
+            @Override
+            public String getValue(JobSummary object) {
+                return object.getJobId();
+            }
+        };
+        idCol.setSortable(true);
+
+        TextColumn<JobSummary> appCol = new TextColumn<JobSummary>() {
+            @Override
+            public String getValue(JobSummary object) {
+                return object.getApplicationName();
+            }
+        };
+        appCol.setSortable(true);
+
+        TextColumn<JobSummary> statusCol = new TextColumn<JobSummary>() {
+            @Override
+            public String getValue(JobSummary object) {
+                return object.getStatus();
+            }
+        };
+        statusCol.setSortable(true);
+
+        /*
+        TextColumn<JobSummary> createTimeCol = new TextColumn<JobSummary>() {
+            @Override
+            public String getValue(JobSummary object) {
+                return renderTime(object.getCreateTime());
+            }
+        };
+        createTimeCol.setSortable(true);
+
+        TextColumn<JobSummary> startTimeCol = new TextColumn<JobSummary>() {
+            @Override
+            public String getValue(JobSummary object) {
+                return renderTime(object.getStartTime());
+            }
+        };
+        startTimeCol.setSortable(true);
+
+        TextColumn<JobSummary> endTimeCol = new TextColumn<JobSummary>() {
+            @Override
+            public String getValue(JobSummary object) {
+                return renderTime(object.getEndTime());
+            }
+        };
+        endTimeCol.setSortable(true);
+        */
+        table.addColumn(idCol, "Job Id");
+        table.addColumn(appCol, "Application Name");
+        table.addColumn(statusCol, "Status");
+        /*
+        table.addColumn(createTimeCol, "Created At");
+        table.addColumn(startTimeCol, "Started At");
+        table.addColumn(endTimeCol, "Finished At");
+        */
+
+        jobSummaryProvider = new AsyncDataProvider<JobSummary>(JobSummary.KEY_PROVIDER) {
+            @Override
+            protected void onRangeChanged(HasData<JobSummary> display) {
+                if (refreshRequestHandler != null) {
+                    refreshRequestHandler.refresh();
+                }
+            }
+        };
+        jobSummaryProvider.addDataDisplay(table);
+    }
+
+    public AsyncDataProvider<JobSummary> getDataProvider() {
+        return jobSummaryProvider;
+    }
+
+    public void setRefreshRequestHandler(IRefreshRequestHandler refreshRequestHandler) {
+        this.refreshRequestHandler = refreshRequestHandler;
+    }
+
+    private static String renderTime(Long time) {
+        if (time < 0) {
+            return "";
+        }
+        return time.toString();
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/JobsTableWidget.ui.xml b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/JobsTableWidget.ui.xml
new file mode 100644
index 0000000..9c48d77
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/JobsTableWidget.ui.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE ui:UiBinder
+  SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"
+>
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+  xmlns:g='urn:import:com.google.gwt.user.client.ui'
+  xmlns:c='urn:import:com.google.gwt.user.cellview.client'>
+  <c:CellTable ui:field="table" width="100%"></c:CellTable>
+</ui:UiBinder>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/NodesTableWidget.java b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/NodesTableWidget.java
new file mode 100644
index 0000000..088619c
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/NodesTableWidget.java
@@ -0,0 +1,102 @@
+package edu.uci.ics.hyracks.adminconsole.client.widgets;
+
+import com.google.gwt.cell.client.ClickableTextCell;
+import com.google.gwt.cell.client.FieldUpdater;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.cellview.client.CellTable;
+import com.google.gwt.user.cellview.client.Column;
+import com.google.gwt.user.cellview.client.TextColumn;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.view.client.AsyncDataProvider;
+import com.google.gwt.view.client.HasData;
+
+import edu.uci.ics.hyracks.adminconsole.client.beans.NodeSummary;
+
+public class NodesTableWidget extends Composite {
+    public interface IRefreshRequestHandler {
+        public void refresh();
+    }
+
+    public interface IClickListener {
+        public void click(String nodeId);
+    }
+
+    interface Binder extends UiBinder<Widget, NodesTableWidget> {
+    }
+
+    private final static Binder binder = GWT.create(Binder.class);
+
+    @UiField
+    CellTable<NodeSummary> table;
+
+    private AsyncDataProvider<NodeSummary> nodeSummaryProvider;
+
+    private IRefreshRequestHandler refreshRequestHandler;
+
+    private IClickListener cl;
+
+    public NodesTableWidget() {
+        initWidget(binder.createAndBindUi(this));
+
+        Column<NodeSummary, String> idCol = new Column<NodeSummary, String>(new ClickableTextCell()) {
+            @Override
+            public String getValue(NodeSummary object) {
+                return object.getNodeId();
+            }
+        };
+        idCol.setFieldUpdater(new FieldUpdater<NodeSummary, String>() {
+            @Override
+            public void update(int index, NodeSummary object, String value) {
+                if (cl != null) {
+                    cl.click(value);
+                }
+            }
+        });
+        idCol.setSortable(true);
+
+        TextColumn<NodeSummary> heapUsedCol = new TextColumn<NodeSummary>() {
+            @Override
+            public String getValue(NodeSummary object) {
+                return String.valueOf(object.getHeapUsed());
+            }
+        };
+        heapUsedCol.setSortable(true);
+
+        TextColumn<NodeSummary> systemLoadAvgCol = new TextColumn<NodeSummary>() {
+            @Override
+            public String getValue(NodeSummary object) {
+                return String.valueOf(object.getSystemLoadAverage());
+            }
+        };
+        systemLoadAvgCol.setSortable(true);
+
+        table.addColumn(idCol, "Node Id");
+        table.addColumn(heapUsedCol, "Heap Used");
+        table.addColumn(systemLoadAvgCol, "System Load Average");
+
+        nodeSummaryProvider = new AsyncDataProvider<NodeSummary>(NodeSummary.KEY_PROVIDER) {
+            @Override
+            protected void onRangeChanged(HasData<NodeSummary> display) {
+                if (refreshRequestHandler != null) {
+                    refreshRequestHandler.refresh();
+                }
+            }
+        };
+        nodeSummaryProvider.addDataDisplay(table);
+    }
+
+    public void setClickListener(IClickListener cl) {
+        this.cl = cl;
+    }
+
+    public AsyncDataProvider<NodeSummary> getDataProvider() {
+        return nodeSummaryProvider;
+    }
+
+    public void setRefreshRequestHandler(IRefreshRequestHandler refreshRequestHandler) {
+        this.refreshRequestHandler = refreshRequestHandler;
+    }
+}
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/NodesTableWidget.ui.xml b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/NodesTableWidget.ui.xml
new file mode 100644
index 0000000..9c48d77
--- /dev/null
+++ b/hyracks-admin-console/src/main/java/edu/uci/ics/hyracks/adminconsole/client/widgets/NodesTableWidget.ui.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE ui:UiBinder
+  SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"
+>
+<ui:UiBinder
+  xmlns:ui='urn:ui:com.google.gwt.uibinder'
+  xmlns:g='urn:import:com.google.gwt.user.client.ui'
+  xmlns:c='urn:import:com.google.gwt.user.cellview.client'>
+  <c:CellTable ui:field="table" width="100%"></c:CellTable>
+</ui:UiBinder>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/resources/edu/uci/ics/hyracks/adminconsole/HyracksAdminConsole.gwt.xml b/hyracks-admin-console/src/main/resources/edu/uci/ics/hyracks/adminconsole/HyracksAdminConsole.gwt.xml
new file mode 100644
index 0000000..765ad1b
--- /dev/null
+++ b/hyracks-admin-console/src/main/resources/edu/uci/ics/hyracks/adminconsole/HyracksAdminConsole.gwt.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module rename-to='HyracksAdminConsole'>
+  <!-- Inherit the core Web Toolkit stuff.                        -->
+  <inherits name='com.google.gwt.user.User' />
+  <inherits name='com.google.gwt.http.HTTP' />
+  <inherits name='com.googlecode.gchart.GChart' />
+
+  <inherits name='com.google.gwt.user.theme.standard.Standard' />
+  <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
+  <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/>     -->
+
+  <!-- Other module inherits                                      -->
+
+  <!-- Specify the app entry point class.                         -->
+  <entry-point class='edu.uci.ics.hyracks.adminconsole.client.HyracksAdminConsole' />
+
+  <!-- Specify the paths for translatable code                    -->
+  <source path='client' />
+
+  <!--set-property name="user.agent" value="safari"></set-property-->
+  <set-configuration-property name="UiBinder.useSafeHtmlTemplates" value="true"/>
+</module>
diff --git a/hyracks-admin-console/src/main/resources/edu/uci/ics/hyracks/adminconsole/client/Messages.properties b/hyracks-admin-console/src/main/resources/edu/uci/ics/hyracks/adminconsole/client/Messages.properties
new file mode 100644
index 0000000..c222555
--- /dev/null
+++ b/hyracks-admin-console/src/main/resources/edu/uci/ics/hyracks/adminconsole/client/Messages.properties
@@ -0,0 +1,2 @@
+sendButton = Send
+nameField = Enter your name
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/webapp/HyracksAdminConsole.css b/hyracks-admin-console/src/main/webapp/HyracksAdminConsole.css
new file mode 100644
index 0000000..7aca7ac
--- /dev/null
+++ b/hyracks-admin-console/src/main/webapp/HyracksAdminConsole.css
@@ -0,0 +1,34 @@
+/** Add css rules here for your application. */
+
+
+/** Example rules used by the template application (remove for your app) */
+h1 {
+  font-size: 2em;
+  font-weight: bold;
+  color: #777777;
+  margin: 40px 0px 70px;
+  text-align: center;
+}
+
+.sendButton {
+  display: block;
+  font-size: 16pt;
+}
+
+/** Most GWT widgets already have a style name defined */
+.gwt-DialogBox {
+  width: 400px;
+}
+
+.dialogVPanel {
+  margin: 5px;
+}
+
+.serverResponseLabelError {
+  color: red;
+}
+
+/** Set ids using widget.getElement().setId("idOfElement") */
+#closeButton {
+  margin: 15px 6px 6px;
+}
diff --git a/hyracks-admin-console/src/main/webapp/HyracksAdminConsole.html b/hyracks-admin-console/src/main/webapp/HyracksAdminConsole.html
new file mode 100644
index 0000000..b909e08
--- /dev/null
+++ b/hyracks-admin-console/src/main/webapp/HyracksAdminConsole.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+    <link type="text/css" rel="stylesheet" href="HyracksAdminConsole.css">
+    <title>Hyracks Administration Console</title>
+    <script type="text/javascript" language="javascript" src="HyracksAdminConsole/HyracksAdminConsole.nocache.js"></script>
+  </head>
+  <body>
+    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
+    <noscript>
+      <div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
+        Your web browser must have JavaScript enabled
+        in order for this application to display correctly.
+      </div>
+    </noscript>
+  </body>
+</html>
\ No newline at end of file
diff --git a/hyracks-admin-console/src/main/webapp/WEB-INF/web.xml b/hyracks-admin-console/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..8c1ab37
--- /dev/null
+++ b/hyracks-admin-console/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE web-app
+    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+    "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+
+  <!-- Servlets -->
+  <!--servlet>
+    <servlet-name>greetServlet</servlet-name>
+    <servlet-class>edu.uci.ics.hyracks.adminconsole.server.GreetingServiceImpl</servlet-class>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>greetServlet</servlet-name>
+    <url-pattern>/HyracksAdminConsole/greet</url-pattern>
+  </servlet-mapping-->
+
+  <!-- Default page to serve -->
+  <welcome-file-list>
+    <welcome-file>HyracksAdminConsole.html</welcome-file>
+  </welcome-file-list>
+
+</web-app>
diff --git a/hyracks-control-cc/pom.xml b/hyracks-control-cc/pom.xml
index f0a13a1..3fed82f 100644
--- a/hyracks-control-cc/pom.xml
+++ b/hyracks-control-cc/pom.xml
@@ -34,7 +34,14 @@
   	<dependency>
   		<groupId>org.eclipse.jetty</groupId>
   		<artifactId>jetty-server</artifactId>
-  		<version>8.0.0.M1</version>
+  		<version>8.0.0.RC0</version>
+  		<type>jar</type>
+  		<scope>compile</scope>
+  	</dependency>
+  	<dependency>
+  		<groupId>org.eclipse.jetty</groupId>
+  		<artifactId>jetty-webapp</artifactId>
+  		<version>8.0.0.RC0</version>
   		<type>jar</type>
   		<scope>compile</scope>
   	</dependency>
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/ClusterControllerService.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/ClusterControllerService.java
index d864c05..cbbef2d 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/ClusterControllerService.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/ClusterControllerService.java
@@ -33,7 +33,6 @@
 
 import edu.uci.ics.hyracks.api.client.ClusterControllerInfo;
 import edu.uci.ics.hyracks.api.client.IHyracksClientInterface;
-import edu.uci.ics.hyracks.api.comm.NetworkAddress;
 import edu.uci.ics.hyracks.api.context.ICCContext;
 import edu.uci.ics.hyracks.api.dataflow.TaskAttemptId;
 import edu.uci.ics.hyracks.api.exceptions.HyracksException;
@@ -66,9 +65,9 @@
 import edu.uci.ics.hyracks.control.common.base.INodeController;
 import edu.uci.ics.hyracks.control.common.context.ServerContext;
 import edu.uci.ics.hyracks.control.common.controllers.CCConfig;
-import edu.uci.ics.hyracks.control.common.controllers.NCConfig;
 import edu.uci.ics.hyracks.control.common.controllers.NodeParameters;
 import edu.uci.ics.hyracks.control.common.controllers.NodeRegistration;
+import edu.uci.ics.hyracks.control.common.heartbeat.HeartbeatData;
 import edu.uci.ics.hyracks.control.common.job.PartitionDescriptor;
 import edu.uci.ics.hyracks.control.common.job.PartitionRequest;
 import edu.uci.ics.hyracks.control.common.job.profiling.om.JobProfile;
@@ -196,9 +195,7 @@
     public NodeParameters registerNode(NodeRegistration reg) throws Exception {
         INodeController nodeController = reg.getNodeController();
         String id = reg.getNodeId();
-        NCConfig ncConfig = reg.getNCConfig();
-        NetworkAddress dataPort = reg.getDataPort();
-        NodeControllerState state = new NodeControllerState(nodeController, ncConfig, dataPort);
+        NodeControllerState state = new NodeControllerState(nodeController, reg);
         jobQueue.scheduleAndSync(new RegisterNodeEvent(this, id, state));
         nodeController.notifyRegistration(this);
         LOGGER.log(Level.INFO, "Registered INodeController: id = " + id);
@@ -259,8 +256,8 @@
     }
 
     @Override
-    public synchronized void nodeHeartbeat(String id) throws Exception {
-        jobQueue.schedule(new NodeHeartbeatEvent(this, id));
+    public synchronized void nodeHeartbeat(String id, HeartbeatData hbData) throws Exception {
+        jobQueue.schedule(new NodeHeartbeatEvent(this, id, hbData));
     }
 
     @Override
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/NodeControllerState.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/NodeControllerState.java
index 2b059b2..21fac2f 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/NodeControllerState.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/NodeControllerState.java
@@ -17,12 +17,19 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import org.json.JSONException;
+import org.json.JSONObject;
+
 import edu.uci.ics.hyracks.api.comm.NetworkAddress;
 import edu.uci.ics.hyracks.api.job.JobId;
 import edu.uci.ics.hyracks.control.common.base.INodeController;
 import edu.uci.ics.hyracks.control.common.controllers.NCConfig;
+import edu.uci.ics.hyracks.control.common.controllers.NodeRegistration;
+import edu.uci.ics.hyracks.control.common.heartbeat.HeartbeatData;
 
 public class NodeControllerState {
+    private static final int RRD_SIZE = 720;
+
     private final INodeController nodeController;
 
     private final NCConfig ncConfig;
@@ -31,17 +38,84 @@
 
     private final Set<JobId> activeJobIds;
 
+    private final String osName;
+
+    private final String arch;
+
+    private final String osVersion;
+
+    private final int nProcessors;
+
+    private final long[] hbTime;
+
+    private final long[] heapInitSize;
+
+    private final long[] heapUsedSize;
+
+    private final long[] heapCommittedSize;
+
+    private final long[] heapMaxSize;
+
+    private final long[] nonheapInitSize;
+
+    private final long[] nonheapUsedSize;
+
+    private final long[] nonheapCommittedSize;
+
+    private final long[] nonheapMaxSize;
+
+    private final int[] threadCount;
+
+    private final int[] peakThreadCount;
+
+    private final double[] systemLoadAverage;
+
+    private int rrdPtr;
+
     private int lastHeartbeatDuration;
 
-    public NodeControllerState(INodeController nodeController, NCConfig ncConfig, NetworkAddress dataPort) {
+    public NodeControllerState(INodeController nodeController, NodeRegistration reg) {
         this.nodeController = nodeController;
-        this.ncConfig = ncConfig;
-        this.dataPort = dataPort;
+        ncConfig = reg.getNCConfig();
+        dataPort = reg.getDataPort();
         activeJobIds = new HashSet<JobId>();
+
+        osName = reg.getOSName();
+        arch = reg.getArch();
+        osVersion = reg.getOSVersion();
+        nProcessors = reg.getNProcessors();
+
+        hbTime = new long[RRD_SIZE];
+        heapInitSize = new long[RRD_SIZE];
+        heapUsedSize = new long[RRD_SIZE];
+        heapCommittedSize = new long[RRD_SIZE];
+        heapMaxSize = new long[RRD_SIZE];
+        nonheapInitSize = new long[RRD_SIZE];
+        nonheapUsedSize = new long[RRD_SIZE];
+        nonheapCommittedSize = new long[RRD_SIZE];
+        nonheapMaxSize = new long[RRD_SIZE];
+        threadCount = new int[RRD_SIZE];
+        peakThreadCount = new int[RRD_SIZE];
+        systemLoadAverage = new double[RRD_SIZE];
+        rrdPtr = 0;
     }
 
-    public void notifyHeartbeat() {
+    public void notifyHeartbeat(HeartbeatData hbData) {
         lastHeartbeatDuration = 0;
+
+        hbTime[rrdPtr] = System.currentTimeMillis();
+        heapInitSize[rrdPtr] = hbData.heapInitSize;
+        heapUsedSize[rrdPtr] = hbData.heapUsedSize;
+        heapCommittedSize[rrdPtr] = hbData.heapCommittedSize;
+        heapMaxSize[rrdPtr] = hbData.heapMaxSize;
+        nonheapInitSize[rrdPtr] = hbData.nonheapInitSize;
+        nonheapUsedSize[rrdPtr] = hbData.nonheapUsedSize;
+        nonheapCommittedSize[rrdPtr] = hbData.nonheapCommittedSize;
+        nonheapMaxSize[rrdPtr] = hbData.nonheapMaxSize;
+        threadCount[rrdPtr] = hbData.threadCount;
+        peakThreadCount[rrdPtr] = hbData.peakThreadCount;
+        systemLoadAverage[rrdPtr] = hbData.systemLoadAverage;
+        rrdPtr = (rrdPtr + 1) % RRD_SIZE;
     }
 
     public int incrementLastHeartbeatDuration() {
@@ -67,4 +141,38 @@
     public NetworkAddress getDataPort() {
         return dataPort;
     }
+
+    public JSONObject toSummaryJSON() throws JSONException {
+        JSONObject o = new JSONObject();
+        o.put("node-id", ncConfig.nodeId);
+        o.put("heap-used", heapUsedSize[(rrdPtr + RRD_SIZE - 1) % RRD_SIZE]);
+        o.put("system-load-average", systemLoadAverage[(rrdPtr + RRD_SIZE - 1) % RRD_SIZE]);
+
+        return o;
+    }
+
+    public JSONObject toDetailedJSON() throws JSONException {
+        JSONObject o = new JSONObject();
+
+        o.put("node-id", ncConfig.nodeId);
+        o.put("os-name", osName);
+        o.put("arch", arch);
+        o.put("os-version", osVersion);
+        o.put("num-processors", nProcessors);
+        o.put("rrd-ptr", rrdPtr);
+        o.put("heartbeat-times", hbTime);
+        o.put("heap-init-sizes", heapInitSize);
+        o.put("heap-used-sizes", heapUsedSize);
+        o.put("heap-committed-sizes", heapCommittedSize);
+        o.put("heap-max-sizes", heapMaxSize);
+        o.put("nonheap-init-sizes", nonheapInitSize);
+        o.put("nonheap-used-sizes", nonheapUsedSize);
+        o.put("nonheap-committed-sizes", nonheapCommittedSize);
+        o.put("nonheap-max-sizes", nonheapMaxSize);
+        o.put("thread-counts", threadCount);
+        o.put("peak-thread-counts", peakThreadCount);
+        o.put("system-load-averages", systemLoadAverage);
+
+        return o;
+    }
 }
\ No newline at end of file
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java
index 798c8a8..8fdde7c 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java
@@ -59,6 +59,12 @@
 
     private JobScheduler js;
 
+    private long createTime;
+
+    private long startTime;
+
+    private long endTime;
+
     private JobStatus status;
 
     private Exception exception;
@@ -95,6 +101,30 @@
         return status;
     }
 
+    public long getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(long createTime) {
+        this.createTime = createTime;
+    }
+
+    public long getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(long startTime) {
+        this.startTime = startTime;
+    }
+
+    public long getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(long endTime) {
+        this.endTime = endTime;
+    }
+
     public synchronized Exception getException() {
         return exception;
     }
@@ -145,6 +175,9 @@
         JSONObject result = new JSONObject();
 
         result.put("job-id", jobId.toString());
+        result.put("create-time", getCreateTime());
+        result.put("start-time", getCreateTime());
+        result.put("end-time", getCreateTime());
 
         JSONArray aClusters = new JSONArray();
         for (ActivityCluster ac : activityClusters) {
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetJobSummariesJSONEvent.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetJobSummariesJSONEvent.java
index bf5e5c3..eda4338 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetJobSummariesJSONEvent.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetJobSummariesJSONEvent.java
@@ -35,7 +35,11 @@
         for (JobRun run : ccs.getRunMap().values()) {
             JSONObject jo = new JSONObject();
             jo.put("type", "job-summary");
-            jo.put("id", run.getJobId().toString());
+            jo.put("job-id", run.getJobId().toString());
+            jo.put("application-name", run.getJobActivityGraph().getApplicationName());
+            jo.put("create-time", run.getCreateTime());
+            jo.put("start-time", run.getCreateTime());
+            jo.put("end-time", run.getCreateTime());
             jo.put("status", run.getStatus().toString());
             summaries.put(jo);
         }
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeEvent.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeDetailsJSONEvent.java
similarity index 70%
copy from hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeEvent.java
copy to hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeDetailsJSONEvent.java
index 0db7f2a..284ec35 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeEvent.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeDetailsJSONEvent.java
@@ -14,26 +14,33 @@
  */
 package edu.uci.ics.hyracks.control.cc.job.manager.events;
 
+import org.json.JSONObject;
+
 import edu.uci.ics.hyracks.control.cc.ClusterControllerService;
 import edu.uci.ics.hyracks.control.cc.NodeControllerState;
 import edu.uci.ics.hyracks.control.cc.jobqueue.SynchronizableEvent;
 
-public class GetNodeEvent extends SynchronizableEvent {
+public class GetNodeDetailsJSONEvent extends SynchronizableEvent {
     private final ClusterControllerService ccs;
     private final String nodeId;
-    private NodeControllerState state;
+    private JSONObject detail;
 
-    public GetNodeEvent(ClusterControllerService ccs, String nodeId) {
+    public GetNodeDetailsJSONEvent(ClusterControllerService ccs, String nodeId) {
         this.ccs = ccs;
         this.nodeId = nodeId;
     }
 
     @Override
     protected void doRun() throws Exception {
-        state = ccs.getNodeMap().get(nodeId);
+        NodeControllerState ncs = ccs.getNodeMap().get(nodeId);
+        if (ncs == null) {
+            detail = new JSONObject();
+            return;
+        }
+        detail = ncs.toDetailedJSON();
     }
 
-    public NodeControllerState getNodeState() {
-        return state;
+    public JSONObject getDetail() {
+        return detail;
     }
 }
\ No newline at end of file
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeEvent.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeSummariesJSONEvent.java
similarity index 70%
rename from hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeEvent.java
rename to hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeSummariesJSONEvent.java
index 0db7f2a..512bce2 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeEvent.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/GetNodeSummariesJSONEvent.java
@@ -14,26 +14,29 @@
  */
 package edu.uci.ics.hyracks.control.cc.job.manager.events;
 
+import org.json.JSONArray;
+
 import edu.uci.ics.hyracks.control.cc.ClusterControllerService;
 import edu.uci.ics.hyracks.control.cc.NodeControllerState;
 import edu.uci.ics.hyracks.control.cc.jobqueue.SynchronizableEvent;
 
-public class GetNodeEvent extends SynchronizableEvent {
+public class GetNodeSummariesJSONEvent extends SynchronizableEvent {
     private final ClusterControllerService ccs;
-    private final String nodeId;
-    private NodeControllerState state;
+    private JSONArray summaries;
 
-    public GetNodeEvent(ClusterControllerService ccs, String nodeId) {
+    public GetNodeSummariesJSONEvent(ClusterControllerService ccs) {
         this.ccs = ccs;
-        this.nodeId = nodeId;
     }
 
     @Override
     protected void doRun() throws Exception {
-        state = ccs.getNodeMap().get(nodeId);
+        summaries = new JSONArray();
+        for (NodeControllerState ncs : ccs.getNodeMap().values()) {
+            summaries.put(ncs.toSummaryJSON());
+        }
     }
 
-    public NodeControllerState getNodeState() {
-        return state;
+    public JSONArray getSummaries() {
+        return summaries;
     }
 }
\ No newline at end of file
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/NodeHeartbeatEvent.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/NodeHeartbeatEvent.java
index 8643e6a..98d17ad 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/NodeHeartbeatEvent.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/manager/events/NodeHeartbeatEvent.java
@@ -20,14 +20,17 @@
 import edu.uci.ics.hyracks.control.cc.ClusterControllerService;
 import edu.uci.ics.hyracks.control.cc.NodeControllerState;
 import edu.uci.ics.hyracks.control.cc.jobqueue.SynchronizableEvent;
+import edu.uci.ics.hyracks.control.common.heartbeat.HeartbeatData;
 
 public class NodeHeartbeatEvent extends SynchronizableEvent {
     private final ClusterControllerService ccs;
     private final String nodeId;
+    private final HeartbeatData hbData;
 
-    public NodeHeartbeatEvent(ClusterControllerService ccs, String nodeId) {
+    public NodeHeartbeatEvent(ClusterControllerService ccs, String nodeId, HeartbeatData hbData) {
         this.ccs = ccs;
         this.nodeId = nodeId;
+        this.hbData = hbData;
     }
 
     @Override
@@ -35,7 +38,7 @@
         Map<String, NodeControllerState> nodeMap = ccs.getNodeMap();
         NodeControllerState state = nodeMap.get(nodeId);
         if (state != null) {
-            state.notifyHeartbeat();
+            state.notifyHeartbeat(hbData);
         }
     }
 
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/AdminConsoleHandler.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/AdminConsoleHandler.java
index a0510f9..8021d1a 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/AdminConsoleHandler.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/AdminConsoleHandler.java
@@ -15,8 +15,7 @@
 package edu.uci.ics.hyracks.control.cc.web;
 
 import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Map;
+import java.net.URL;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -26,51 +25,21 @@
 import org.eclipse.jetty.server.handler.AbstractHandler;
 
 import edu.uci.ics.hyracks.control.cc.ClusterControllerService;
-import edu.uci.ics.hyracks.control.cc.NodeControllerState;
-import edu.uci.ics.hyracks.control.cc.jobqueue.SynchronizableEvent;
 
 public class AdminConsoleHandler extends AbstractHandler {
-    private ClusterControllerService ccs;
-
     public AdminConsoleHandler(ClusterControllerService ccs) {
-        this.ccs = ccs;
     }
 
     @Override
     public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
             throws IOException, ServletException {
-        if (!"/".equals(target)) {
-            return;
+        String basedir = System.getProperty("basedir");
+        if (basedir == null) {
+            response.getWriter().println("No Administration Console found.");
         }
-        response.setContentType("text/html;charset=utf-8");
-        response.setStatus(HttpServletResponse.SC_OK);
-        baseRequest.setHandled(true);
-        final PrintWriter writer = response.getWriter();
-        writer.println("<html><head><title>Hyracks Admin Console</title></head><body>");
-        writer.println("<h1>Hyracks Admin Console</h1>");
-        writer.println("<h2>Node Controllers</h2>");
-        writer.println("<table><tr><td>Node Id</td><td>Host</td></tr>");
-        try {
-            ccs.getJobQueue().scheduleAndSync(new SynchronizableEvent() {
-                @Override
-                protected void doRun() throws Exception {
-                    for (Map.Entry<String, NodeControllerState> e : ccs.getNodeMap().entrySet()) {
-                        try {
-                            writer.print("<tr><td>");
-                            writer.print(e.getKey());
-                            writer.print("</td><td>");
-                            writer.print(e.getValue().getLastHeartbeatDuration());
-                            writer.print("</td></tr>");
-                        } catch (Exception ex) {
-                        }
-                    }
-                }
-            });
-        } catch (Exception e) {
-            throw new IOException(e);
-        }
-        writer.println("</table>");
-        writer.println("</body></html>");
-        writer.flush();
+
+        URL url = new URL(request.getRequestURL().toString());
+        String ccLoc = url.getProtocol() + "://" + url.getHost() + ":" + url.getPort();
+        response.sendRedirect("/console?cclocation=" + ccLoc);
     }
 }
\ No newline at end of file
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/RESTAPIFunction.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/JobsRESTAPIFunction.java
similarity index 95%
rename from hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/RESTAPIFunction.java
rename to hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/JobsRESTAPIFunction.java
index a488d2f..bd46276 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/RESTAPIFunction.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/JobsRESTAPIFunction.java
@@ -24,10 +24,10 @@
 import edu.uci.ics.hyracks.control.cc.job.manager.events.GetJobSummariesJSONEvent;
 import edu.uci.ics.hyracks.control.cc.web.util.IJSONOutputFunction;
 
-public class RESTAPIFunction implements IJSONOutputFunction {
+public class JobsRESTAPIFunction implements IJSONOutputFunction {
     private ClusterControllerService ccs;
 
-    public RESTAPIFunction(ClusterControllerService ccs) {
+    public JobsRESTAPIFunction(ClusterControllerService ccs) {
         this.ccs = ccs;
     }
 
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/NodesRESTAPIFunction.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/NodesRESTAPIFunction.java
new file mode 100644
index 0000000..9059de7
--- /dev/null
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/NodesRESTAPIFunction.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.hyracks.control.cc.web;
+
+import org.json.JSONObject;
+
+import edu.uci.ics.hyracks.control.cc.ClusterControllerService;
+import edu.uci.ics.hyracks.control.cc.job.manager.events.GetNodeDetailsJSONEvent;
+import edu.uci.ics.hyracks.control.cc.job.manager.events.GetNodeSummariesJSONEvent;
+import edu.uci.ics.hyracks.control.cc.web.util.IJSONOutputFunction;
+
+public class NodesRESTAPIFunction implements IJSONOutputFunction {
+    private ClusterControllerService ccs;
+
+    public NodesRESTAPIFunction(ClusterControllerService ccs) {
+        this.ccs = ccs;
+    }
+
+    @Override
+    public JSONObject invoke(String[] arguments) throws Exception {
+        JSONObject result = new JSONObject();
+        switch (arguments.length) {
+            case 1: {
+                if ("".equals(arguments[0])) {
+                    GetNodeSummariesJSONEvent gnse = new GetNodeSummariesJSONEvent(ccs);
+                    ccs.getJobQueue().scheduleAndSync(gnse);
+                    result.put("result", gnse.getSummaries());
+                } else {
+                    String nodeId = arguments[0];
+                    GetNodeDetailsJSONEvent gnde = new GetNodeDetailsJSONEvent(ccs, nodeId);
+                    ccs.getJobQueue().scheduleAndSync(gnde);
+                    result.put("result", gnde.getDetail());
+                }
+            }
+        }
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/WebServer.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/WebServer.java
index efbc8f7..fb5ad21 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/WebServer.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/web/WebServer.java
@@ -14,6 +14,9 @@
  */
 package edu.uci.ics.hyracks.control.cc.web;
 
+import java.io.File;
+import java.util.logging.Logger;
+
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.Server;
@@ -21,12 +24,15 @@
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
 import org.eclipse.jetty.server.handler.HandlerCollection;
 import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.webapp.WebAppContext;
 
 import edu.uci.ics.hyracks.control.cc.ClusterControllerService;
 import edu.uci.ics.hyracks.control.cc.web.util.JSONOutputRequestHandler;
 import edu.uci.ics.hyracks.control.cc.web.util.RoutingHandler;
 
 public class WebServer {
+    private final static Logger LOGGER = Logger.getLogger(WebServer.class.getName());
+
     private final ClusterControllerService ccs;
     private final Server server;
     private final SelectChannelConnector connector;
@@ -48,17 +54,30 @@
     private void addHandlers() {
         ContextHandler handler = new ContextHandler("/rest");
         RoutingHandler rh = new RoutingHandler();
-        rh.addHandler("jobs", new JSONOutputRequestHandler(new RESTAPIFunction(ccs)));
+        rh.addHandler("jobs", new JSONOutputRequestHandler(new JobsRESTAPIFunction(ccs)));
+        rh.addHandler("nodes", new JSONOutputRequestHandler(new NodesRESTAPIFunction(ccs)));
         handler.setHandler(rh);
         addHandler(handler);
 
-        handler = new ContextHandler("/admin");
+        handler = new ContextHandler("/adminconsole");
         handler.setHandler(new AdminConsoleHandler(ccs));
         addHandler(handler);
 
         handler = new ContextHandler("/applications");
         handler.setHandler(new ApplicationInstallationHandler(ccs));
         addHandler(handler);
+
+        String basedir = System.getProperty("basedir");
+        if (basedir != null) {
+            File warFile = new File(basedir, "console/hyracks-admin-console.war");
+            LOGGER.info("Looking for admin console binary in: " + warFile.getAbsolutePath());
+            if (warFile.exists()) {
+                WebAppContext waCtx = new WebAppContext();
+                waCtx.setContextPath("/console");
+                waCtx.setWar(warFile.getAbsolutePath());
+                addHandler(waCtx);
+            }
+        }
     }
 
     public void setPort(int port) {
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/base/IClusterController.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/base/IClusterController.java
index 6ff4901..ba0bc86 100644
--- a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/base/IClusterController.java
+++ b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/base/IClusterController.java
@@ -21,6 +21,7 @@
 import edu.uci.ics.hyracks.api.job.JobId;
 import edu.uci.ics.hyracks.control.common.controllers.NodeParameters;
 import edu.uci.ics.hyracks.control.common.controllers.NodeRegistration;
+import edu.uci.ics.hyracks.control.common.heartbeat.HeartbeatData;
 import edu.uci.ics.hyracks.control.common.job.PartitionDescriptor;
 import edu.uci.ics.hyracks.control.common.job.PartitionRequest;
 import edu.uci.ics.hyracks.control.common.job.profiling.om.JobProfile;
@@ -36,7 +37,7 @@
 
     public void notifyTaskFailure(JobId jobId, TaskAttemptId taskId, String nodeId, Exception e) throws Exception;
 
-    public void nodeHeartbeat(String id) throws Exception;
+    public void nodeHeartbeat(String id, HeartbeatData hbData) throws Exception;
 
     public void reportProfile(String id, List<JobProfile> profiles) throws Exception;
 
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/base/INodeController.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/base/INodeController.java
index 33548d9..efaa921 100644
--- a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/base/INodeController.java
+++ b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/base/INodeController.java
@@ -25,7 +25,6 @@
 import edu.uci.ics.hyracks.api.job.JobId;
 import edu.uci.ics.hyracks.api.partitions.PartitionId;
 import edu.uci.ics.hyracks.control.common.controllers.NCConfig;
-import edu.uci.ics.hyracks.control.common.controllers.NodeCapability;
 import edu.uci.ics.hyracks.control.common.job.TaskAttemptDescriptor;
 
 public interface INodeController extends Remote {
@@ -33,8 +32,6 @@
 
     public NCConfig getConfiguration() throws Exception;
 
-    public NodeCapability getNodeCapability() throws Exception;
-
     public void startTasks(String appName, JobId jobId, byte[] planBytes, List<TaskAttemptDescriptor> taskDescriptors,
             Map<ConnectorDescriptorId, IConnectorPolicy> connectorPolicies, byte[] ctxVarBytes) throws Exception;
 
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/NodeCapability.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/NodeCapability.java
deleted file mode 100644
index 7ad5fa1..0000000
--- a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/NodeCapability.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009-2010 by The Regents of the University of California
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * you may obtain a copy of the License from
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package edu.uci.ics.hyracks.control.common.controllers;
-
-import java.io.Serializable;
-
-public class NodeCapability implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private int cpuCount;
-
-    public int getCPUCount() {
-        return cpuCount;
-    }
-
-    public void setCPUCount(int cpuCount) {
-        this.cpuCount = cpuCount;
-    }
-}
\ No newline at end of file
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/NodeRegistration.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/NodeRegistration.java
index 374cf48..9b10d27 100644
--- a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/NodeRegistration.java
+++ b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/NodeRegistration.java
@@ -30,11 +30,24 @@
 
     private final NetworkAddress dataPort;
 
-    public NodeRegistration(INodeController nc, String nodeId, NCConfig ncConfig, NetworkAddress dataPort) {
+    private final String osName;
+
+    private final String arch;
+
+    private final String osVersion;
+
+    private final int nProcessors;
+
+    public NodeRegistration(INodeController nc, String nodeId, NCConfig ncConfig, NetworkAddress dataPort,
+            String osName, String arch, String osVersion, int nProcessors) {
         this.nc = nc;
         this.nodeId = nodeId;
         this.ncConfig = ncConfig;
         this.dataPort = dataPort;
+        this.osName = osName;
+        this.arch = arch;
+        this.osVersion = osVersion;
+        this.nProcessors = nProcessors;
     }
 
     public INodeController getNodeController() {
@@ -52,4 +65,20 @@
     public NetworkAddress getDataPort() {
         return dataPort;
     }
+
+    public String getOSName() {
+        return osName;
+    }
+
+    public String getArch() {
+        return arch;
+    }
+
+    public String getOSVersion() {
+        return osVersion;
+    }
+
+    public int getNProcessors() {
+        return nProcessors;
+    }
 }
\ No newline at end of file
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/heartbeat/HeartbeatData.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/heartbeat/HeartbeatData.java
new file mode 100644
index 0000000..1816cd5
--- /dev/null
+++ b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/heartbeat/HeartbeatData.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.hyracks.control.common.heartbeat;
+
+import java.io.Serializable;
+
+public class HeartbeatData implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    public long heapInitSize;
+    public long heapUsedSize;
+    public long heapCommittedSize;
+    public long heapMaxSize;
+    public long nonheapInitSize;
+    public long nonheapUsedSize;
+    public long nonheapCommittedSize;
+    public long nonheapMaxSize;
+    public int threadCount;
+    public int peakThreadCount;
+    public long totalStartedThreadCount;
+    public double systemLoadAverage;
+}
\ No newline at end of file
diff --git a/hyracks-control-nc/src/main/java/edu/uci/ics/hyracks/control/nc/NodeControllerService.java b/hyracks-control-nc/src/main/java/edu/uci/ics/hyracks/control/nc/NodeControllerService.java
index 4eb1a03..28cb8be 100644
--- a/hyracks-control-nc/src/main/java/edu/uci/ics/hyracks/control/nc/NodeControllerService.java
+++ b/hyracks-control-nc/src/main/java/edu/uci/ics/hyracks/control/nc/NodeControllerService.java
@@ -18,6 +18,12 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Serializable;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryUsage;
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.lang.management.ThreadMXBean;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.rmi.registry.LocateRegistry;
@@ -75,9 +81,9 @@
 import edu.uci.ics.hyracks.control.common.base.INodeController;
 import edu.uci.ics.hyracks.control.common.context.ServerContext;
 import edu.uci.ics.hyracks.control.common.controllers.NCConfig;
-import edu.uci.ics.hyracks.control.common.controllers.NodeCapability;
 import edu.uci.ics.hyracks.control.common.controllers.NodeParameters;
 import edu.uci.ics.hyracks.control.common.controllers.NodeRegistration;
+import edu.uci.ics.hyracks.control.common.heartbeat.HeartbeatData;
 import edu.uci.ics.hyracks.control.common.job.TaskAttemptDescriptor;
 import edu.uci.ics.hyracks.control.common.job.profiling.om.JobProfile;
 import edu.uci.ics.hyracks.control.common.job.profiling.om.JobletProfile;
@@ -103,8 +109,6 @@
 
     private final IHyracksRootContext ctx;
 
-    private final NodeCapability nodeCapability;
-
     private final PartitionManager partitionManager;
 
     private final ConnectionManager connectionManager;
@@ -123,6 +127,14 @@
 
     private final Map<String, NCApplicationContext> applications;
 
+    private final MemoryMXBean memoryMXBean;
+
+    private final ThreadMXBean threadMXBean;
+
+    private final RuntimeMXBean runtimeMXBean;
+
+    private final OperatingSystemMXBean osMXBean;
+
     public NodeControllerService(NCConfig ncConfig) throws Exception {
         this.ncConfig = ncConfig;
         id = ncConfig.nodeId;
@@ -131,7 +143,6 @@
         if (id == null) {
             throw new Exception("id not set");
         }
-        nodeCapability = computeNodeCapability();
         connectionManager = new ConnectionManager(ctx, getIpAddress(ncConfig));
         partitionManager = new PartitionManager(this);
         connectionManager.setPartitionRequestListener(partitionManager);
@@ -141,6 +152,10 @@
         serverCtx = new ServerContext(ServerContext.ServerType.NODE_CONTROLLER, new File(new File(
                 NodeControllerService.class.getName()), id));
         applications = new Hashtable<String, NCApplicationContext>();
+        memoryMXBean = ManagementFactory.getMemoryMXBean();
+        threadMXBean = ManagementFactory.getThreadMXBean();
+        runtimeMXBean = ManagementFactory.getRuntimeMXBean();
+        osMXBean = ManagementFactory.getOperatingSystemMXBean();
     }
 
     public IHyracksRootContext getRootContext() {
@@ -164,7 +179,8 @@
         Registry registry = LocateRegistry.getRegistry(ncConfig.ccHost, ncConfig.ccPort);
         IClusterController cc = (IClusterController) registry.lookup(IClusterController.class.getName());
         this.nodeParameters = cc.registerNode(new NodeRegistration(this, id, ncConfig, connectionManager
-                .getNetworkAddress()));
+                .getNetworkAddress(), osMXBean.getName(), osMXBean.getArch(), osMXBean.getVersion(), osMXBean
+                .getAvailableProcessors()));
 
         // Schedule heartbeat generator.
         timer.schedule(new HeartbeatTask(cc), 0, nodeParameters.getHeartbeatPeriod());
@@ -190,11 +206,6 @@
         return id;
     }
 
-    @Override
-    public NodeCapability getNodeCapability() throws Exception {
-        return nodeCapability;
-    }
-
     public ConnectionManager getConnectionManager() {
         return connectionManager;
     }
@@ -207,12 +218,6 @@
         return ccs;
     }
 
-    private static NodeCapability computeNodeCapability() {
-        NodeCapability nc = new NodeCapability();
-        nc.setCPUCount(Runtime.getRuntime().availableProcessors());
-        return nc;
-    }
-
     private static InetAddress getIpAddress(NCConfig ncConfig) throws Exception {
         String ipaddrStr = ncConfig.dataIPAddress;
         ipaddrStr = ipaddrStr.trim();
@@ -411,14 +416,31 @@
     private class HeartbeatTask extends TimerTask {
         private IClusterController cc;
 
+        private final HeartbeatData hbData;
+
         public HeartbeatTask(IClusterController cc) {
             this.cc = cc;
+            hbData = new HeartbeatData();
         }
 
         @Override
         public void run() {
+            MemoryUsage heapUsage = memoryMXBean.getHeapMemoryUsage();
+            hbData.heapInitSize = heapUsage.getInit();
+            hbData.heapUsedSize = heapUsage.getUsed();
+            hbData.heapCommittedSize = heapUsage.getCommitted();
+            hbData.heapMaxSize = heapUsage.getMax();
+            MemoryUsage nonheapUsage = memoryMXBean.getNonHeapMemoryUsage();
+            hbData.nonheapInitSize = nonheapUsage.getInit();
+            hbData.nonheapUsedSize = nonheapUsage.getUsed();
+            hbData.nonheapCommittedSize = nonheapUsage.getCommitted();
+            hbData.nonheapMaxSize = nonheapUsage.getMax();
+            hbData.threadCount = threadMXBean.getThreadCount();
+            hbData.peakThreadCount = threadMXBean.getPeakThreadCount();
+            hbData.totalStartedThreadCount = threadMXBean.getTotalStartedThreadCount();
+            hbData.systemLoadAverage = osMXBean.getSystemLoadAverage();
             try {
-                cc.nodeHeartbeat(id);
+                cc.nodeHeartbeat(id, hbData);
             } catch (Exception e) {
                 e.printStackTrace();
             }
diff --git a/hyracks-server/pom.xml b/hyracks-server/pom.xml
index 4d69304..73819b3 100644
--- a/hyracks-server/pom.xml
+++ b/hyracks-server/pom.xml
@@ -72,5 +72,12 @@
   		<type>jar</type>
   		<scope>compile</scope>
   	</dependency>
+  	<dependency>
+  		<groupId>edu.uci.ics.hyracks</groupId>
+  		<artifactId>hyracks-admin-console</artifactId>
+  		<version>0.1.8-SNAPSHOT</version>
+  		<type>war</type>
+  		<scope>compile</scope>
+  	</dependency>
   </dependencies>
 </project>
diff --git a/hyracks-server/src/main/assembly/binary-assembly.xml b/hyracks-server/src/main/assembly/binary-assembly.xml
index cd598d9..72af28b 100644
--- a/hyracks-server/src/main/assembly/binary-assembly.xml
+++ b/hyracks-server/src/main/assembly/binary-assembly.xml
@@ -5,6 +5,16 @@
     <format>dir</format>
   </formats>
   <includeBaseDirectory>false</includeBaseDirectory>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>console</outputDirectory>
+      <fileMode>0644</fileMode>
+      <includes>
+        <include>edu.uci.ics.hyracks:hyracks-admin-console</include>
+      </includes>
+      <outputFileNameMapping>${artifact.artifactId}.${artifact.extension}</outputFileNameMapping>
+    </dependencySet>
+  </dependencySets>
   <fileSets>
     <fileSet>
       <directory>target/appassembler/bin</directory>
diff --git a/pom.xml b/pom.xml
index 32fc946..6771a7a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,10 @@
       <id>hyracks-public</id>
       <url>http://obelix.ics.uci.edu/nexus/content/groups/hyracks-public/</url>
     </repository>
+    <repository>
+      <id>jboss-public</id>
+      <url>https://repository.jboss.org/nexus/content/groups/public/</url>
+    </repository>
   </repositories>
 
   <pluginRepositories>
@@ -67,6 +71,7 @@
     <module>hyracks-dataflow-std</module>
     <module>hyracks-dataflow-hadoop</module>
     <module>hyracks-control-common</module>
+    <module>hyracks-admin-console</module>
     <module>hyracks-control-cc</module>
     <module>hyracks-control-nc</module>
     <module>hyracks-cli</module>