Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Overview

Why GWT?  I am currently working on a client project that required a rich user interface experience.  Developing the interactivity with manual javascript (prototype) coding was painfully slow and difficult to get working consistently across multiple browser versions.

...

  • Part 1 : create a basic GWT component
  • Part 2 : make the GWT component talk to an ofbiz service

Caveat

1) Use these instructions at your own risk!
2) I still have a lot to learn about GWT so there maybe a better way of achieving what is described here.
3) The build scripts are not optimised.
4) I develop on a linux laptop. Some of the commands will be different if you are using Windows.

Pre-requisites

1) These instructions assume you are working on the latest ofbiz r924549 and only tested with the Tomahawk theme.
2) You are familiar with ofbiz development, if not read the tutorial at OFBiz Tutorial - A Beginners Development Guide
3) You are familiar with GWT, if not read the tutorials at http://code.google.com/webtoolkit/doc/latest/tutorial/index.html

Step 1 - setup GWT

Download GWT SDK (I used GWT 2.0.3).Unzip GWT into OFBIZ_HOME. My OFBIZ directory looks like this:

Code Block
ofbiz
  +- applications
  +- bin
  +- debian
  +- framework
  +- gwt-2.0.3
       +- doc
       +- samples
  +- hot-deploy
  +- runtime
  +- specialpurpose
  +- themes
  +- tools

Step 2 - create an ofbiz component

Code Block
snowch@dl:~/workspace/ofbiz$ ./ant create-component
Buildfile: build.xml
Trying to override old definition of datatype javacc
Trying to override old definition of datatype jjtree

create-component:
    [input] Component name: (e.g. mycomponent) [Mandatory]
gwtdemo
    [input] Component resource name: (e.g. MyComponent) [Mandatory]
GwtDemo
    [input] Webapp name: (e.g. mycomponent) [Mandatory]
gwtdemo
    [input] Base permission: (e.g. MYCOMPONENT) [Mandatory]
GWTDEMO
     [echo] The following hot-deploy component will be created:
     [echo]               Name: gwtdemo
     [echo]               Resource Name: GwtDemo
     [echo]               Webapp Name: gwtdemo
     [echo]               Base permission: GWTDEMO
     [echo]               Folder: /home/snowch/workspace/ofbiz/hot-deploy/gwtdemo
     [echo]
    [input] Confirm:  (Y, [N], y, n)
y

Step X - create GWT module descriptor

Create the gwt module descriptor xml file: src/org/example/gwtdemo.gwt.xml

...

The module rename-to value should be the same as your component name.
We will create the entry-point class later in this tutorial.

Step x - Edit the component build.xml file

Add the following properties to your build.xml file below the <import file="../../common.xml"/> tag

...

Code Block

    <!-- ================================================================= -->
    <!--                                                  GWT Targets                                     -->
    <!-- ================================================================= -->
	
	<target name="libs" description="Copy libs to ${build}/lib">
		<mkdir dir="${build.dir}/lib" />
		<copy todir="${build.dir}/lib" file="${gwt.sdk}/gwt-servlet.jar" />
		<!-- Add any additional server libs that need to be copied -->
	</target>
	
	<target name="javac" depends="libs" description="Compile java source">
		<mkdir dir="${build.dir}/classes"/>
		<javac srcdir="src" includes="**" encoding="utf-8"
        destdir="${build.dir}/classes"
        source="1.5" target="1.5" nowarn="true"
        debug="true" debuglevel="lines,vars,source">
			<classpath refid="local.class.path"/>
		</javac>
		<copy todir="${build.dir}/classes">
			<fileset dir="src" excludes="**/*.java"/>
		</copy>
	</target>

	<target name="gwtc" depends="javac" description="GWT compile to JavaScript">
		<java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
			<classpath>
				<pathelement location="src"/>
				<path refid="local.class.path"/>
			</classpath>
			<!-- add jvmarg -Xss16M or similar if you see a StackOverflowError -->
			<jvmarg value="-Xmx256M"/>
			<!-- Additional arguments like -style PRETTY or -logLevel DEBUG -->
			<arg line="${gwt.args}"/>
			<arg value="${gwt.webapp.name}"/>
		</java>
	</target>

	<target name="jar" depends="javac, gwtc">
		<jar jarfile="${build.dir}/lib/${name}.jar">
			<fileset dir="${build.dir}/classes"/>
		</jar>
	</target>

	<target name="build" depends="gwtc, jar" description="Build this project" />

Step x - create the GWT entry point class

Create the following file: src/org/example/client/gwtdemo.java

Code Block
package org.example.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.RootPanel;

public class gwtdemo implements EntryPoint {

    public void onModuleLoad() {
	  
    final Button helloButton = new Button("Say Hello");
  
    helloButton.addClickHandler(new ClickHandler() {
		@Override
		public void onClick(ClickEvent arg0) {
			DialogBox dialog = new DialogBox();
			dialog.setAutoHideEnabled(true);
			dialog.setText("Hello World");
			dialog.center();
			dialog.show();
		}
    });
    
    RootPanel.get("helloButtonContainer").add(helloButton);
  }
}

Step x - test that the ant build works

change to your component's top level folder and run ant

...

The build process compiles the java gwtdemo.java class into javascript, html and images files and puts them in the webapp/gwtdemo/gwtpages/gwtdemo folder.

Grant web access to the gwtpages folder

Add the ":/gwtdemo.css:/gwtpages" to allowedPaths in web.xml:

Code Block
        <init-param>
            <param-name>allowedPaths</param-name>
            <param-value>/control:/select:/index.html:/index.jsp:/default.html:/default.jsp:/images:/includes/maincss.css:/gwtdemo.css:/gwtpages</param-value>
        </init-param>

Step x - add a page to the main screen

Code Block
<?xml version="1.0" encoding="UTF-8"?>
<screens xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/widget-screen.xsd">

    <screen name="main">
        <section>
            <actions>
            	<set field="headerItem" value="main"/><!-- this highlights the selected menu-item with name = "main" -->
            	<!-- ========================================================= -->
            	<!-- load the gwt generated javascript and a custom stylesheet -->
            	<!-- ========================================================= -->
            	<set field="layoutSettings.javaScripts[+0]" value="/gwtdemo/gwtpages/gwtdemo/gwtdemo.nocache.js" global="true"/>
            	<set field="layoutSettings.styleSheets[+0]" value="/gwtdemo/gwtdemo.css" global="true"/> 				            	
            </actions>
            <widgets>
                <decorator-screen name="GwtDemoCommonDecorator" location="${parameters.mainDecoratorLocation}">
                    <decorator-section name="body">
                    	<!-- ===================================== -->
                    	<!-- Add a page to load the gwt javascript -->
                    	<!-- ===================================== -->
                    	<platform-specific>
                    		<html><html-template location="component://gwtdemo/webapp/gwtdemo/gwtdemo.ftl"/></html>
                    	</platform-specific>                    
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>
</screens>

Step x - create the webapp/gwtdemo/gwtdemo.ftl page

Create the gwtdemo.ftl page that is used to load the gwt pages.

Code Block
<!doctype html>

    <!-- OPTIONAL: include this if you want history support -->
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
    
    <!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
    <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>

    <h1>Web Application Starter Project</h1>

    <table align="center">
      <tr>
        <td id="helloButtonContainer"></td>
      </tr>
    </table>

Step x - create the webapp/gwtdemo/gwtdemo.css page

Code Block
/** 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;
}

Step x - Grant admin user access to your page

Either grant admin user GWTDEMO_VIEW permission, or comment out widget/CommonScreens.xml permission condition:

Code Block
    <screen name="GwtDemoCommonDecorator">
        <section>
            <actions>
            </actions>
            <widgets>
                <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
                    <decorator-section name="body">
                        <section>
<!--
                            <condition>
                                <if-has-permission permission="GWTDEMO" action="_VIEW"/>
                            </condition>
-->
                            <widgets>
                                <decorator-section-include name="body"/>
                            </widgets>
                            <fail-widgets>
                                <label style="h3">${uiLabelMap.GwtDemoViewPermissionError}</label>
                            </fail-widgets>
                        </section>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>

TODO

Single browser compilation:

...