Click here to Skip to main content
15,891,136 members
Articles / Web Development / HTML

GWT in Action, 2nd Edition - Using GWT Properties to Drive Deferred Binding

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
26 May 2011CPOL9 min read 22.7K   3  
A Chapter excerpt from GWT in Action, 2nd Edition - Using GWT Properties to Drive Deferred Binding
image002.jpgGWT in Action, Second Edition

Ian Bambury, Christopher Ramsdale, Robert Hanson, Adam Tacy

GWT properties are defined in a module XML file. This article from the book GWT in Action, Second Edition, discusses how to define, extend, set, and use properties.

To save 35% on your next purchase use Promotional Code tacy21635 when you check out at www.manning.com.

You may also be interested in…

GWT properties are defined in a module XML file. They are, in some way, a combination of a Java enumerations and a variable—we can list the possible values for a property and define the actual value it has.

We’re going to cover both views of a property, starting with its enumeration view as we define what a property is and what values it can take (either initially defined or when extended). After that, we will look at how we set the value a property should have, by setting it directly, or conditionally. Setting the property value needs a bit more of a description than defining the property, and, since we need to define the property before we can do anything with it, that is where we will start.

Defining Properties

To define a property and the set of values it can take, you use a <define-property> tag. For example, the GWT-provided user.agent property is defined in the UserAgent module (in the com.google.gwt.user package) as:

<define-property name="user.agent"
               values="ie6,ie8,gecko,gecko1_8,safari,opera"/>

The set of values in user.agent is not expected to be altered by the programmer, though you might do so if you want to support a different rendering engine yourself. Internationalization, on the other hand, is defined in the I18N module (in package com.google.gwt.i18n). This defines only one value for its property: 

<define-property name="locale" values="default" />

The programmer would add the locale to this property to tell the GWT compiler to create locale-specific permutations. You do this by extending the property.

Extending Properties

To introduce a new locale, you extend the locale property using the <extend-property> tag, in your application’s module file. Adding the French, country-independent locale is achieved using:

<extend-property name="locale" values="fr" />

This means there are now two values for the locale property in your application: default and fr. You can extend the property with as many values as you like. Each value added increases the permutation space.

Setting Properties

In addition to defining a list of possible values for a property (where it acts similar to a Java enumeration), a property can also hold a particular value. (Now it acts similar to a variable.)  The value can be set either directly in a module file, or programmatically at runtime. 

Setting a property value directly is done in a module file using the <set-property> tag. It does not make sense to set the user.agent directly since we do not know which browser the user is using, so we will quickly look at another GWT-provided property: gwt.enableDebugId. This property is provided in the Debug module in the com.google.gwt.debug package. It enables us to give widgets particular id values in the DOM so we can see what is going on in our application in a DOM inspection tool more easily. 

We get the result shown in figure 1 if we write this code:

Label aLabel = new Label("Check this Label’s ID");
aLabel.ensureDebugId("DEBUG LABEL");

and turn on GWT’s enable debug id functionality by setting the gwt.enableDebugId property to true as follows:

<set-property name="gwt.enableDebugId" value="true"/>

 image003.gif

Figure 1 A GWT Label displayed in Safari, with Safari’s Web Development tool open showing HTML, in particular the div representing the Label shows our debug id of gwt-debug-DEBUG LABEL as the div’s id value.

In figure 1, we can see our label is the div element of the body and that the element has been given the ID we requested, prefixed with the text gwt-debug. If we had set gwt.enableDebugId to false, this id would not appear. (In fact, the code for it would have been compiled out by the compiler.) By default, gwt.enableDebugId is set to true but, since we don’t typically use the ensureDebugId method in our code, you don’t see the result in the DOM.

An Old Tip

Before GWT 2.0’s web mode browser plugins, to test your code in a browser that wasn’t built into your operating system version of GWT meant compiling you code. That could take some time as there are at least six permutations.  To make things quicker, you could limit the permutations using the set-property tag. Adding the following to your application’s module file limits browser permutations to just Opera:

<set-property name="user.agent" value ="opera"/>

It is unlikely you need to do this for GWT 2.0 because you just use the plugin in your chosen browser.

One thing to note is that GWT always uses the last definition in module files, so you need to be careful of order.  If you have the following two lines in you module, then the locale will have value en as it is written second:

<set-property name="locale" value="fr"/>

<set-property name="locale" value="en"/>

There is the same issue to watch for when inheriting GWT modules. If there is a module MyModule that sets the locale to fr, and MyOtherModule that sets it to en, then local will be still be set to en:

<inherits name="com.manning.gwtia.MyModule"/>

<inherits name="com.mannig.gwtia.MyOtherModule"/>

This ordering might sometimes cause an issue if you don’t have a clear view of what is being set where, it can be used to our advantage. 

As of GWT 2.0, we are able to set properties conditionally, adding some more capability for us to look at and potentially use.

Conditionally Setting a Property

New for GWT 2.0 is the ability to set a property value conditionally based on the values of other properties. This is useful for several reasons including creating derived properties and minimizing the number of permutations produced. 

GWT uses this first approach to enable us as programmers to turn on a JavaScript Stack emulation mode. This just means that GWT will not rely on the browsers call stack, if it has one, to report things such as error traces, but will emulate one of its own.

An emulated stack is a large step forward for debugging compiled code on IE (which doesn’t have its own useful stack). Normally, when an exception is thrown in IE, the best you get is a vague reference to a line number in obfuscated JavaScript code. (You could compile your program so detailed you get a reference to clearer JavaScript than obfuscated letters in code, but that is still not that great.) With an emulated stack, you get the filename, line numbers, and the call stack. (See figure 2 for an example). Much more impressive than a null object on line 4837 of obfuscated code—we are sure you agree!

image004.jpg

Figure 2 View of an exception in IE using the emulated stack functionality of GWT 2.0, turned on by setting emulatedStack property to true. Notice that, even though the function names are obfuscated in JavaScript, the stack output includes the filename and the line number of the original Java files!

The functionality is contained in the EmulateJsStack module within the com.google.gwt.core module. The full definition can be seen in listing 1.

Listing 1 GWT Module Definition of the Conditional Property for EmulataJsStack

  <define-property name="compiler.emulatedStack"                     |#1
                 values="true,false" />                              |#1
  <set-property name="compiler.emulatedStack" value="false" />       |#1
  <define-property name="compiler.stackMode"                         |#2
                 values="strip,native,emulated" />                   |#2
  <set-property name="compiler.stackMode" value="native" />          |#2
 
  <set-property name="compiler.stackMode" value="emulated" >         |#3
    <when-property-is name="compiler.emulatedStack" value="true" />  |#3
  </set-property> 
#1 Defining the first property>
#2 Defining the second property>
#3 Conditionally setting a value>

This definition is not that different from what we have already seen. In #1, it defines the property compiler.emulatedStack. This is the property that we as programmers will set, has a nice logical true/false value, and is initially set to false. Next, it defines the compiler.stackMode property, which can have values strip, native or emulated, and sets it initially to native (#2).

Using the fact that GWT processes definitions in order, the code at #3 will change the value of compiler.stackMode to true, if compiler.emulatedStack is set to true at some point in the future. That is something you can do in your own module, which we did to get figure 2.

Conditions can be grouped together to indicate various Boolean conditions using the tags: <any>, <all>, or <none>. The <any> tag implies that at least one of the conditions is true, <all> requires all the conditions to be true, and <none> acts as a not (or nor if multiple conditions are contained). This definition identifies all non Microsoft browsers.

<set-property name="non.microsoft" value= "true">                  
   <none>
      <when-property-is name="user.agent" value="ie6"/>
      <when-property-is name="user.agent" value="ie8"/>
   </none>
</set-property>

If you need a different code implementation for Internet Explorer, you signal that using a replace-with tag as follows:

<replace-with class="com.manning.MyDom_IE">                  
   <when-type-is class="com.manning.MyDom"/>                   
   <any>                                                       
      <when-property-is name="user.agent" value="ie6"/>        
      <when-property-is name="user.agent" value="ie8"/>        
   </any>                                                      
</replace-with>

Now that we know about conditional properties, we can write this a different way, as shown in listing 2.

Listing 2 Simple Deferred Binding Replacing a Class if we are Dealing with Any of the IE Browsers (Using Conditional Properties)

<define-property name="isIE" values="true, false"/>             #1
<set-property name="isIE" value="false"/>                       #1
<set-property name="isIE" value="true">                        |#2 
   <any>                                                       |#2
      <when-property-is name="user.agent" value="ie6"/>        |#2
      <when-property-is name="user.agent" value="ie8"/>        |#2
   </any>                                                      |#2
</set-property>                                                |#2
 
<replace-with class="com.manning.MyDom_IE">                  
   <when-type-is class="com.manning.MyDom"/>                   
   <when-property-is name="isIE" value="true"/>                 #3
</replace-with>
#1 Defining a new property>
#3 Conditionally setting the value for IE>
#4 Replacing based on new property>

In this newer approach, we define a new property (#1) that will be false for all browsers (#2) except for ie6 or ie8 (#3). The <replace-with> tag is simplified to use the new property. 

Within GWT, we can create our own properties using any the techniques we have just seen. We will use this ability to enhance our debug ability.

Creating and Using our own Properties

Let’s say we want a little control over enabling debug ids on elements and emulating the JavaScript stack in our compiler code. What we want to do is turn both these functionalities off if we are running normally in production and turn them both on if we are compiling to debug an issue. Listing 3 shows what we will set up to achieve this.

Listing 3 Own defined Properties and Conditional Setting for Debug and Production mode Compilation

  <inherits name='com.google.gwt.core.EmulateJsStack'/>           
  <inherits name='com.google.gwt.debug.Debug'/>                   
  
  <define-property name="dev.mode" values="debug,prod"/>           #1
   
  <set-property name="compiler.emulatedStack" value="false" />    |#2 
  <set-property name="gwt.enableDebugId" value="false" />         |#2
            
  <set-property name="compiler.emulatedStack" value="true" >      |#3   
     <when-property-is name="dev.mode" value="debug" />           |#3    
  </set-property>                                                 |#3
  <set-property name="gwt.enableDebugId" value="true" >           |#3
     <when-property-is name="dev.mode" value="debug" />           |#3 
  </set-property>                                                 |#3   

    
  <set-property name="dev.mode" value="debug"/>                    #4
#1 Defining the new property>
#2 Setting the initial values>
#3 Conditionally setting the value>
#4 Setting dev.mode property>

We first inherit the modules we will be using, and do that at #1, inheriting EmulateJsStack and Debug modules.  At #2, we define our new property, which we choose to call dev.mode and let it have values debug and prod.  Next, we set GWT’s properties to false (#3) as the default case.

The code at #4 is where the values of compiler.emulatedStack and gwt.enableDebugId are set to true if dev.mode is set somewhere in the future to a value of debug. 

If we do set dev.mode to debug in the future then we get the debug functionality, otherwise we do not. We do it here, but it could be done in any module file that inherits this one.

Summary

We’ve seen what properties drive, how we define and extend the values they could take, and how to set particular values. Building on all that, we defined our own dev.mode property and used it. 

Here are some other Manning titles you might be interested in:

image005.jpg

Grails in Action
Glen Smith and Peter Ledbrook

image006.jpg

Griffon in Action
Andres Almiray, Danno Ferrin, and James Shingler

image007.jpg

Spring in Action, Third Edition
Craig Walls

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --