Pages

Showing posts with label GWT. Show all posts
Showing posts with label GWT. Show all posts

Friday, 20 September 2013

GWTModuleBase URL and HostPageBase URL

http://stackoverflow.com/q/12615663

Say I'm hosting a project at http://example.com/foo. I put all of the GWT files (which are generated in the /war/ directory after compiling) in http://example.com/foo/GwtModule directory.
Then on my host page, which is http://example.com/foo/bar, I put the following in the HTML:
<script type="text/javascript" src="http://example.com/foo/GwtModule/GwtModule.noCache.js"></script>.
My questions are:
  • Will GWT know to fetch its resources (e.g css files) from foo/GwtModule folder rather than trying to get them from foo/bar folder?
  • If I wanted to send a HTTP request to foo/signup, would GWT.getModuleBaseUrl() + "signup" work or will I have to parse the base url, remove "/bar" from it and replace it with "/signup"?
  • If I run the code locally as well as on a web server, will GWT automatically determine if the base url is http://localhost/foo/bar or http://example.com/foo/bar , or do I need to hard-code the base urls somewhere?
 http://stackoverflow.com/a/12618532
Will GWT know to fetch its resources (e.g css files) from foo/GwtModule folder rather than trying to get them from foo/bar folder?
Yes.
GWT always resolves the module base from the script URL (or a special <meta name='gwt:property'>)
If I wanted to send a HTTP request to foo/signup, would GWT.getModuleBaseUrl() + "signup" work or will I have to parse the base url, remove "/bar" from it and replace it with "/signup"?
GWT.getModuleBaseURL() will be /foo/GwtModule/.
You can either use GWT.getModuleBaseURL() + "/../signup" or "GWT.getHostPageBaseURL() + "/signup", in your case they'll both resolve to the same /foo/signup URL.
If I run the code locally as well as on a web server, will GWT automatically determine if the base url is http://localhost/foo/bar or http://example.com/foo/bar, or do I need to hard-code the base urls somewhere?
See answer to first question.
That means you'll have to use <script src="GwtModule/GwtModule.nocache.js"> or <script src="/foo/GwtModule/GwtModule.nocache.js"> in your host page.

Wednesday, 4 September 2013

URL, URI, Context Path, path info

Consider following servlet conf 
 <servlet>
        <servlet-name>NewServlet</servlet-name>
        <servlet-class>NewServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>NewServlet</servlet-name>
        <url-pattern>/NewServlet/*</url-pattern>
    </servlet-mapping>
Now When I hit url http://localhost:8084/JSPTemp1/NewServlet/jhi it will invoke NewServlet as it is mapped with pattern.
here
getRequestURI() =  /JSPTemp1/NewServlet/jhi
getPathInfo() = /jhi
getPathInfo()
returns
a String, decoded by the web container, specifying extra path information that comes after the servlet path but before the query string in the request URL; or null if the URL does not have any extra path information
getRequestURI()
returns
a String containing the part of the URL from the protocol name up to the query string



Its very important to know how container picks a servlet from which web app .(means how it identify the correct web app and then correct servlet)

Since the request uri consist of three main parts
Context Path- this helps container to choose the correct web app
ServletPath-this helps container to identify correct servlet into the from the requested web app.
PathInfo-in case of directory match

So if the request uri is
http://server.com/MyApp/servlet/xyz ,the container will first look for a web app named MyApp if it exists then it will look for the resource(here servlet) mapped to /servlet/xyz.

In case if there is no web app named MyApp then it (Tomcat)will look into the default web app (ROOT) for the servlet mapped to the uri /MyApp/servlet/xyz and proceed acc to that.

Monday, 10 December 2012

Deferred Binding

Coding Basics - Deferred Binding

Deferred binding is a feature of the GWT compiler that works by generating many versions of code at compile time, only one of which needs to be loaded by a particular client during bootstrapping at runtime. Each version is generated on a per browser basis, along with any other axis that your application defines or uses. For example, if you were to internationalize your application using GWT's Internationalization module, the GWT compiler would generate various versions of your application per browser environment, such as "Firefox in English", "Firefox in French", "Internet Explorer in English", etc... As a result, the deployed JavaScript code is compact and quicker to download than hand coded JavaScript, containing only the code and resources it needs for a particular browser environment.
  1. Deferred Binding Benefits
  2. Defining Deferred Binding Rules
  3. Directives in Module XML files
  4. Deferred Binding Using Replacement
  5. Example Class Hierarchy using Replacement
  6. Deferred Binding using Generators
  7. Generator Configuration in Module XML
  8. Generator Implementation

Deferred Binding Benefits

Deferred Binding is a technique used by the GWT compiler to create and select a specific implementation of a class based on a set of parameters. In essence, deferred binding is the Google Web Toolkit answer to Java reflection. It allows the GWT developer to produce several variations of their applications custom to each browser environment and have only one of them actually downloaded and executed in the browser.
Deferred binding has several benefits:
  • Reduces the size of the generated JavaScript code that a client will need to download by only including the code needed to run a particular browser/locale instance (used by the Internationalization module)
  • Saves development time by automatically generating code to implement an interface or create a proxy class (used by the GWT RPC module)
  • Since the implementations are pre-bound at compile time, there is no run-time penalty to look up an implementation in a data structure as with dynamic binding or using virtual functions.
Some parts of the toolkit make implicit use of deferred binding, that is, they use the technique as a part of their implementation, but it is not visible to the user of the API. For example, many widgets and panels as well as the DOM class use this technique to implement browser specific logic. Other GWT features require the API user to explicity invoke deferred binding by designing classes that follow specific rules and instantiating instances of the classes with GWT.create(Class), including GWT RPC and I18N.
As a user of the Google Web Toolkit, you may never need to create a new interface that uses deferred binding. If you follow the instructions in the guide for creating internationalized applications or GWT RPC calls you will be using deferred binding, but you will not have to actually write any browser dependent or locale dependent code.
The rest of the deferred binding section describes how to create new rules and classes using deferred binding. If you are new to the toolkit or only intend to use pre-packaged widgets, you will probably want to skip on to the next topic. If you are interested in programming entirely new widgets from the ground up or other functionality that requires cross-browser dependent code, the next sections should be of interest.

Defining Deferred Binding Rules

There are two ways in which types can be replaced via deferred binding:
  • Replacement: A type is replaced with another depending on a set of configurable rules.
  • Code generation: A type is substituted by the result of invoking a code genreator at compile time.

Directives in Module XML files

The deferred binding mechanism is completely configurable and does not require editing the GWT distributed source code. Deferred binding is configured through the <replace-with> and <generate-with> elements in the module XML files. The deferred binding rules are pulled into the module build through <inherits> elements.
For example, the following configuration invokes deferred binding for the PopupPanel widget:
Inside the PopupPanel module XML file, there happens to be some rules defined for deferred binding. In this case, we're using a replacement rule.

Deferred Binding Using Replacement

The first type of deferred binding uses replacement. Replacement means overriding the implementation of one java class with another that is determined at compile time. For example, this technique is used to conditionalize the implementation of some widgets, such as the PopupPanel. The use of <inherits> for the PopupPanel class is shown in the previous section describing the deferred binding rules. The actual replacement rules are specified in Popup.gwt.xml, as shown below:
<module> 
 
  <!--  ... other configuration omitted ... --> 
 
  <!-- Fall through to this rule is the browser isn't IE or Mozilla --> 
  <replace-with class="com.google.gwt.user.client.ui.impl.PopupImpl"> 
    <when-type-is class="com.google.gwt.user.client.ui.impl.PopupImpl"/> 
  </replace-with> 
 
  <!-- Mozilla needs a different implementation due to issue #410 --> 
  <replace-with class="com.google.gwt.user.client.ui.impl.PopupImplMozilla"> 
    <when-type-is class="com.google.gwt.user.client.ui.impl.PopupImpl" /> 
    <any> 
      <when-property-is name="user.agent" value="gecko"/> 
      <when-property-is name="user.agent" value="gecko1_8" /> 
    </any> 
  </replace-with> 
 
  <!-- IE has a completely different popup implementation --> 
  <replace-with class="com.google.gwt.user.client.ui.impl.PopupImplIE6"> 
    <when-type-is class="com.google.gwt.user.client.ui.impl.PopupImpl"/> 
    <when-property-is name="user.agent" value="ie6" /> 
  </replace-with> </module>
These directives tell the GWT compiler to swap out the PoupImpl class code with different class implementations according to the the user.agent property. The Popup.gwt.xml file specifies a default implementation for the PopupImpl class, an overide for the Mozilla browser (PopupImplMozilla is substituted for PopupImpl), and an override for Internet Explorer version 6 (PopupImplIE6 is substituted for PopupImpl). Note that PopupImpl class or its derived classes cannot be instantiated directly. Instead, the PopupPanel class is used and the GWT.create(Class) technique is used under the hood to instruct the compiler to use deferred binding.

Example Class Hierarchy using Replacement

To see how this is used when designing a widget, we will examine the case of the PopupPanel widget further. The PopupPanel class implements the user visible API and contains logic that is common to all browsers. It also instantiates the proper implementation specific logic using the GWT.create(Class) as follows:
  private static final PopupImpl impl = GWT.create(PopupImpl.class);
The two classes PopupImplMozilla and PopupImplIE6 extend the PopupImpl class and override some PopupImpl's methods to implement browser specific behavior.
Then, when the PopupPanel class needs to switch to some browser dependent code, it accesses a member function inside the PopupImpl class:
  public void setVisible(boolean visible) { 
    // ... common code for all implementations of PopupPanel ... 
 
    // If the PopupImpl creates an iframe shim, it's also necessary to hide it 
    // as well. 
    impl.setVisible(getElement(), visible); 
  }
The default implementation of PopupImpl.setVisible() is empty, but PopupImplIE6 has some special logic implemented as a JSNI method:
  public native void setVisible(Element popup, boolean visible) /*-{ 
    if (popup.__frame) { 
      popup.__frame.style.visibility = visible ? 'visible' : 'hidden'; 
    } 
  }-*/;{
After the GWT compiler runs, it prunes out any unused code. If your application references the PopupPanel class, the compiler will create a separate JavaScript output file for each browser, each containing only one of the implementations: PopupImpl, PopupImplIE6 or PopupImplMozilla. This means that each browser only downloads the implementation it needs, thus reducing the size of the output JavaScript code and minimizing the time needed to download your application from the server.

Deferred Binding using Generators

The second technique for deferred binding consists of using generators. Generators are classes that are invoked by the GWT compiler to generate a Java implementation of a class during compilation. When compiling for production mode, this generated implementation is directly translated to one of the versions of your application in JavaScript code that a client will download based on its browser environment.
The following is an example of how a deferred binding generator is specified to the compiler in the module XML file hierarchy for the RemoteService class - used for GWT-RPC:

Generator Configuration in Module XML

The XML element <generate-with> tells the compiler to use a Generator class. Here are the contents of the RemoteService.gwt.xml file relevant to deferred binding:
<module> 
 
 <!--  ... other configuration omitted ... --> 
 
 <!-- Default warning for non-static, final fields enabled --> 
 <set-property name="gwt.suppressNonStaticFinalFieldWarnings" value="false" /> 
 
 <generate-with class="com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator"> 
   <when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService" /> 
 </generate-with> </module>
These directives instruct the GWT compiler to invoke methods in a Generator subclass (ServiceInterfaceProxyGenerator) in order to generate special code when the deferred binding mechanism GWT.create() is encountered while compiling. In this case, if the GWT.create() call references an instance of RemoteService or one of its subclasses, the ServiceInterfaceProxyGenerator's generate()` method will be invoked.

Generator Implementation

Defining a subclass of the Generator class is much like defining a plug-in to the GWT compiler. The Generator gets called to generate a Java class definition before the Java to JavaScript conversion occurs. The implementation consists of one method that must output Java code to a file and return the name of the generated class as a string.
The following code shows the Generator that is responsible for deferred binding of a RemoteService interface:
/** 
 * Generator for producing the asynchronous version of a 
 * {@link com.google.gwt.user.client.rpc.RemoteService RemoteService} interface. 
 */ public class ServiceInterfaceProxyGenerator extends Generator { 
 
  /** 
   * Generate a default constructible subclass of the requested type. The 
   * generator throws <code>UnableToCompleteException</code> if for any reason 
   * it cannot provide a substitute class 
   * 
   * @return the name of a subclass to substitute for the requested class, or 
   *         return <code>null</code> to cause the requested type itself to be 
   *         used 
   * 
   */ 
  public String generate(TreeLogger logger, GeneratorContext ctx, 
      String requestedClass) throws UnableToCompleteException { 
 
    TypeOracle typeOracle = ctx.getTypeOracle(); 
    assert (typeOracle != null); 
 
    JClassType remoteService = typeOracle.findType(requestedClass); 
    if (remoteService == null) { 
      logger.log(TreeLogger.ERROR, "Unable to find metadata for type '" 
          + requestedClass + "'", null); 
      throw new UnableToCompleteException(); 
    } 
 
    if (remoteService.isInterface() == null) { 
      logger.log(TreeLogger.ERROR, remoteService.getQualifiedSourceName() 
          + " is not an interface", null); 
      throw new UnableToCompleteException(); 
    } 
 
    ProxyCreator proxyCreator = new ProxyCreator(remoteService); 
 
    TreeLogger proxyLogger = logger.branch(TreeLogger.DEBUG, 
        "Generating client proxy for remote service interface '" 
            + remoteService.getQualifiedSourceName() + "'", null); 
 
    return proxyCreator.create(proxyLogger, ctx); 
  } }
The typeOracle is an object that contains information about the Java code that has already been parsed that the generator may need to consult. In this case, the generate() method checks it arguments and the passes off the bulk of the work to another class (ProxyCreator).
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License.

Thursday, 1 November 2012

GWT Google Map

Source: http://code.google.com/p/gwt-google-maps-v3/wiki/GettingStarted

Maps Getting Started

Using Google Maps in a GWT project

Getting Started

The Google Maps API provides a convenient JavaScript API which allows you to add mapping functionality to your application. The Google Maps library for GWT allows you to access this JavaScript API from Java code compiled with the GWT compiler.

Assumptions

Downloading the Google Maps Library for GWT

Download latest release from project's download page. Copy downloaded library jar to your projects lib folder(create one if not already present).

Creating a new GWT Project

Start by creating a new GWT project named SimpleMaps as described in the Google Plugin for Eclipse user's guide.
Since we are working with an additional library, add gwt-maps3.jar to the Java classpath. Then, add the inherits line for com.google.gwt.maps.Maps to your module i.e com.example.google.gwt.mapstutorial.SimpleMaps.gwt.xml in our case.
  <inherits name='com.google.gwt.maps.Maps' />

Adding the Maps script tag to your module XML file

Your GWT application will need access to the Maps API, as well as the API key. In order to do this, you must include a
<script>
tag in your module's SimpleMaps.gwt.xml file. Include the script tag shown in your module.xml file above the automatically generated stylesheet reference.
  <script src="http://maps.google.com/maps/api/js?sensor=false" />

Update the HTML host file

Replace the body of the HTML host file war/SimpleMaps.html with a <div> tag that we can use for the GWT application.
  <body>

    <h1>SimpleMaps</h1>

    <div id="mapsTutorial"></div>

  </body>

Add a map object to .java source

To complete the src/com/example/google/gwt/mapstutorial/client/SimpleMaps.java file, add some imports, a member to store a MapWidget instance, and replace the body of the onModuleLoad() method.

package com.example.google.gwt.mapstutorial.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.maps.client.MapOptions;
import com.google.gwt.maps.client.MapTypeId;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.user.client.ui.RootPanel;
public class SimpleMaps implements EntryPoint {
  private MapWidget mapWidget;

  // GWT module entry point method.
  public void onModuleLoad() {
    final MapOptions options = new MapOptions();
    // Zoom level. Required
    options.setZoom(8);
    // Open a map centered on Cawker City, KS USA. Required
    options.setCenter(new LatLng(39.509, -98.434));
    // Map type. Required.
    options.setMapTypeId(new MapTypeId().getRoadmap());
    
    // Enable maps drag feature. Disabled by default.
    options.setDraggable(true);
    // Enable and add default navigation control. Disabled by default.
    options.setNavigationControl(true);
    // Enable and add map type control. Disabled by default.
    options.setMapTypeControl(true);
    mapWidget = new MapWidget(options);
    mapWidget.setSize("800px", "600px");
    
    
    // Add the map to the HTML host page
    RootPanel.get("mapsTutorial").add(mapWidget);
  }
}

Run the SimpleMaps sample project

Now you should be able to execute your sample project in dev mode by using the Run configuration from Eclipse.

Tuesday, 30 October 2012

Basic File Upload in GWT

Client: 
 
public class FileUploader{

    private ControlPanel cp;
    private FormPanel form = new FormPanel();
    private FileUpload fu =  new FileUpload();

    public FileUploader(ControlPanel cp) {
     this.cp = cp;
     this.cp.setPrimaryArea(getFileUploaderWidget());
    }

    @SuppressWarnings("deprecation")
    public Widget getFileUploaderWidget() {
     form.setEncoding(FormPanel.ENCODING_MULTIPART);
     form.setMethod(FormPanel.METHOD_POST);
     // form.setAction(/* WHAT SHOULD I PUT HERE */);

     VerticalPanel holder = new VerticalPanel();

     fu.setName("upload");
     holder.add(fu);
     holder.add(new Button("Submit", new ClickHandler() {
      public void onClick(ClickEvent event) {
       GWT.log("You selected: " + fu.getFilename(), null);
       form.submit();
      }
     }));

     form.addSubmitHandler(new FormPanel.SubmitHandler() {
      public void onSubmit(SubmitEvent event) {
       if (!"".equalsIgnoreCase(fu.getFilename())) {
        GWT.log("UPLOADING FILE????", null);
                                        // NOW WHAT????
       }
       else{
        event.cancel(); // cancel the event
       }

      }
     });

     form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
      public void onSubmitComplete(SubmitCompleteEvent event) {
       Window.alert(event.getResults());
      }
     });

     form.add(holder);

     return form;
    }
}
 
Server:
 
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.apache.commons.fileupload.FileItemIterator; 
import org.apache.commons.fileupload.FileItemStream; 
import org.apache.commons.fileupload.servlet.ServletFileUpload; 

public class FileUpload extends HttpServlet{
    public void doPost(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
        ServletFileUpload upload = new ServletFileUpload();

        try{
            FileItemIterator iter = upload.getItemIterator(request);

            while (iter.hasNext()) {
                FileItemStream item = iter.next();

                String name = item.getFieldName();
                InputStream stream = item.openStream();


                // Process the input stream
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int len;
                byte[] buffer = new byte[8192];
                while ((len = stream.read(buffer, 0, buffer.length)) != -1) {
                    out.write(buffer, 0, len);
                }

                int maxFileSize = 10*(1024*1024); //10 megs max 
                if (out.size() > maxFileSize) { 
                    throw new RuntimeException("File is > than " + maxFileSize);
                }
            }
        }
        catch(Exception e){
            throw new RuntimeException(e);
        }

    }
} 

web.xml
<servlet>
    <servlet-name>fileUploaderServlet</servlet-name>
    <servlet-class>com.testapp.server.FileUpload</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>fileUploaderServlet</servlet-name>
  <url-pattern>/testapp/fileupload</url-pattern>
</servlet-mapping>
 
 
And: 
form.setAction(GWT.getModuleBaseURL()+"fileupload"); 

3 steps for uploading files in GWT

 Source: http://www.gwttutorial.com/gwt-development/gwt-upload-in-3-easy-steps

3 steps for uploading files in GWT

gwt development There are several very fancy and easy to use GWT Upload libraries that you can use in your applications but sometimes you just need a very simple interface to add an upload functionality to your application.  While the GWT client side of the upload process is the easiest part, many people miss the little tweak that you need to use.
If you want to use one of the fancier upload libraries for cool effects like upload status, I would recommend using GWT-Upload, GwtUpload, or Upload4Gwt.
In order to add this to your page, follow these three easy steps…

Step 1: Create a file upload servlet

There are tons of examples across the internet showing how to do this.  The easiest way is to use the Apache Commons FileUpload library.  An example of a fairly trivial use of this library looks like this:


 Step 2: Modify web.xml

If you are writing a servlet, it goes without saying that you need to add an entry into the web.xml file.
The <servlet> tag tells the web server that you have a class and you want it known by this servlet name.  Then in the <servlet-mapping>, you tell it that the class known by this name, should be invoked when the given URL pattern is requested.
At this point the server is done and all you need is to make the client side of the task

Step 3: GWT Upload Form

Create a FormPanel and add it to your page. The most important part of this code is the FormPanel.ENCODING_MULTIPART and FormPanel.METHOD_POST.

 Conclusion

As you can see, it is simple to an upload functionality to your app.  Now if you do want to add more flash to your look and feel (and who doesn’t like flashy stuff), I would highly recommend using the libraries I suggested above, GWT-UploadGwtUpload, or Upload4Gwt.  They do a fabulous job.  Here is an example of what Upload4Gwt looks like.

gwt development

Tuesday, 9 October 2012

GWT Custom Event

Events in general:

Events are always sent to inform about something (e.g. a change of state). Let's take your example with a man and a wall. Here we can imagine that there is a game where a user can walk as a man in a labyrinth. Every time a user hits the wall it should be informed about the collision so that it can react to it (e.g. a wall can render itself as a destroyed wall). This can be achieved by sending a collision event every time the collision with a wall is detected. This event is sent by a man and every object in the system interested in the event receives it and can react to it accordingly. Objects which want to receive events must register themselves as interested with event.
This is how events work in general in every system or framework (not only in GWT). In order to send and receive events in such systems you have to define:
  1. What is sent (what do events look like)
  2. Who receives events (event receivers)
  3. Who sends events (event senders)
Then you can:
  1. Register event receivers which want to receive events
  2. Send events

Events in GWT:

Here I will show an example of using custom events in GWT. I will use an example of a system which is responsible for checking a mailbox and inform a user if there are new mails. Let's assume that in the system there are at least 2 components:
  • message checker responsible for checking the mailbox and
  • message displayer responsible for displaying new mails
Message checker sends events when a new mail is received and message displayer receives these events.

Step 1: Define events

Information about a new mail will be sent as an instance of MessageReceivedEvent class. The class contains a new mail (for the simplicity let's assume it is just a String).
Full source code of this class is presented below (the comment for it is below the source code).
public class MessageReceivedEvent extends GwtEvent<MessageReceivedEventHandler> {

    public static Type<MessageReceivedEventHandler> TYPE = new Type<MessageReceivedEventHandler>();

    private final String message;

    public MessageReceivedEvent(String message) {
        this.message = message;
    }

    @Override
    public Type<MessageReceivedEventHandler> getAssociatedType() {
        return TYPE;
    }

    @Override
    protected void dispatch(MessageReceivedEventHandler handler) {
        handler.onMessageReceived(this);
    }

    public String getMessage() {
        return message;
    }
}
MessageReceivedEventHandler is an interface that represents event receivers. Don't bother with it at the moment, this will be discussed later.
Every class representing a GWT event has to extend GwtEvent class. This class contains two abstract methods which must be implemented: getAssociatedType and dispatch. However in every event class they are usually implemented in a very similar way.
The class stores information about a received message (see constructor). Every event receiver can get it using getMessage method.

Step 2: Define event receivers

Each event type in GWT is associated to an interface representing receivers of this event type. In GWT receivers are called handlers. In the example an event receiver interface for MessageReceivedEvent will be named MessageReceivedEventHandler. The source code is below:
public interface MessageReceivedEventHandler extends EventHandler {
    void onMessageReceived(MessageReceivedEvent event);
}
Each handler has to extend EventHandler interface. It should also define a method which will be invoked when an event occurs (it should take at least one parameter - an event). Here the method is named onMessageReceived. Each receiver can react on an event by implementing this method.
The only event receiver in the example is MessageDisplayer component:
public class MessageDisplayer implements MessageReceivedEventHandler {

    @Override
    public void onMessageReceived(MessageReceivedEvent event) {
        String newMessage = event.getMessage();
        // display a new message
        // ...
    }

}

Step 3: Define event senders

In the example the only event sender is a component responsible for checking mails - EventChecker:
public class MessageChecker implements HasHandlers {

    private HandlerManager handlerManager;

    public MessageChecker() {
        handlerManager = new HandlerManager(this);
    }

    @Override
    public void fireEvent(GwtEvent<?> event) {
        handlerManager.fireEvent(event);
    }

    public HandlerRegistration addMessageReceivedEventHandler(
            MessageReceivedEventHandler handler) {
        return handlerManager.addHandler(MessageReceivedEvent.TYPE, handler);
    }

}
Every event sender has to implement HasHandlers interface.
The most important element here is a HandlerManager field. In GWT HandlerManager as the name suggest manages event handlers (event receivers). As it was said at the beginning every event receiver that wants to receive events must register itself as interested. This is what handler managers are for. They make it possible to register event handlers an they can send a particular event to every registered event handler.
When a HanlderManager is created it takes one argument in its constructor. Every event has a source of origin and this parameter will be used as a source for all events send by this handler manager. In the example it is this as the source of events is MessageChecker.
The method fireEvent is defined in HasHandlers interface and is responsible for sending events. As you can see it just uses a handler manager to send (fire) and event.
addMessageReceivedEventHandler is used by event receivers to register themselves as interested in receiving events. Again handler manager is used for this.

Step 4: Bind event receivers with event senders

When everything is defined event receivers must register themselves in event senders. This is usually done during creation of objects:
MessageChecker checker = new MessageChecker();
MessageDisplayer displayer = new MessageDisplayer();
checker.addMessageReceivedEventHandler(displayer);
Now all events sent by checker will be received by displayer.

Step 5: Send events

To send an event, MessageChecker must create an event instance and send it using fireEvent method. This cane be done in newMailReceived method:
public class MessageChecker implements HasHandlers {

    // ... not important stuff omitted

    public void newMailReceived() {
        String mail = ""; // get a new mail from mailbox
        MessageReceivedEvent event = new MessageReceivedEvent(mail);
        fireEvent(event);
    }

}

Thursday, 13 September 2012

GWT UiBinder

From http://blog.jeffdouglas.com/2010/01/19/gwt-uibinder-hello-world-tutorial/




GWT UiBinder Hello World Tutorial

January 19th, 2010
I’ve been working on a new project the past couple of weeks that (fortunately) requires Google Web Toolkit (GWT) and I wanted to use the new UiBinder that was released with GWT 2.0 in early December for a number of reasons (clean separation of UI and code, easier collaboration with designers, easier testing, etc ). However, I was having a hard time getting my head wrapped around it given that the GWT site has very little documentation and only a few examples. I’ve combed through the message boards, the docs and the sample Mail application that comes with the SDK and after finally groking the new functionality, I put together a little Hello World app, the kind that would have helped me out originally.
So I’m making some assumptions that you already have the GWT SDK and Eclipse Plugin installed and are familiar with both of them. If you are not, take a look at the GWT site for more info.
To get started, create a new Web Application Project called “HelloUiBinder” in the package of your choice but do not check “Use Google App Engine”.

Now create a new UiBinder template and owner class (File -> New -> UiBinder). Choose the client package for the project and then name it MyBinderWidget. Leave all of the other defaults. When you click Finish the plugin will create a new UiBinder template and owner class.

Open the MyBinderWidget.ui.xml template and add the following code. With GWT you can define your styles either in your template where you need them or externally. I’ve added a small style inline that adds some pizzaz to the label. Notice the field name myPanelContent in the template. You can programmatically read and write to this field from the template’s owner class. So when the owner class runs, it construct a new VerticalPanel, does something with it (probably add some type of content) and then fill this field with it.
Attributes for the elements (the text attribute in the Label element for example) correspond to a setter method for the widget. Unfortunately there is no code completion to get a list of these attributes in Eclipse when you hit the space bar so you either have to know the setters or refer to the JavaDocs each time. A painful process.
1
2
3
4
5
6
7
8
9
10
11
<!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">
     <ui:style>
          .bolder { font-weight:bold; }
     </ui:style>
     <g:HTMLPanel>
          <g:Label styleName="{style.bolder}" text="This is my label in bold!"/>
          <g:VerticalPanel ui:field="myPanelContent" spacing="5"/>
     </g:HTMLPanel>
</ui:UiBinder>
For the owner class, MyBinderWidget.java, add the following code. In this class, a field with the same name, myPanelContent, is marked with the @UiField annotation. When uiBinder.createAndBindUi(this) is run, the content is created for the VerticalPanel and the template field is filled with the new instance.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.jeffdouglas.client;
 
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.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
 
public class MyBinderWidget extends Composite {
 
     private static MyBinderWidgetUiBinder uiBinder = GWT
               .create(MyBinderWidgetUiBinder.class);
 
     interface MyBinderWidgetUiBinder extends UiBinder<widget, MyBinderWidget> { }
 
     @UiField VerticalPanel myPanelContent;
 
     public MyBinderWidget() {
          initWidget(uiBinder.createAndBindUi(this));
 
          HTML html1 = new HTML();
          html1.setHTML("<a href='http://www.google.com'>Click me!</a>");
          myPanelContent.add(html1);
          HTML html2 = new HTML();
          html2.setHTML("This is my sample <b>content</b>!");
          myPanelContent.add(html2);
 
     }
 
}
Now change the entry point class to look like the following.
1
2
3
4
5
6
7
8
9
10
11
12
package com.jeffdouglas.client;
 
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
 
public class HelloUiBinder implements EntryPoint {
 
     public void onModuleLoad() {
          MyBinderWidget w = new MyBinderWidget();
          RootPanel.get().add(w);
     }
}
Now open HelloUiBinder.html and remove all of the HTML content between the </noscript> and and </body> save it. Once you run the application, copy the development URL and run paste it into your favorite supported browser, you should see the following.

Now suppose you wanted to nest a widget inside your MyBinderWidget that did something when a button was clicked. We’ll create a small series of checkboxes that allows the user to select their favorite colors and display them when the button is clicked. Create a new UiBinder called FavoriteColorWidget in the client package. Add the following code to the FavoriteColorWidget.ui.xml template.
1
2
3
4
5
6
7
8
9
10
11
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
    <g:VerticalPanel>
      <g:Label ui:field="greeting"/>
      <g:Label>Choose your favorite color(s):</g:Label>
      <g:CheckBox ui:field="red" formValue="red">Red</g:CheckBox>
      <g:CheckBox ui:field="white" formValue="white">White</g:CheckBox>
      <g:CheckBox ui:field="blue" formValue="blue">Blue</g:CheckBox>
      <g:Button ui:field="button">Submit</g:Button>
    </g:VerticalPanel>
</ui:UiBinder>
Now add the click handler in the FavoriteColorWidget.java owner class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.jeffdouglas.client;
 
import java.util.ArrayList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
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.Button;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
 
public class FavoriteColorWidget extends Composite {
 
     private static FavoriteColorWidgetUiBinder uiBinder = GWT
               .create(FavoriteColorWidgetUiBinder.class);
 
     interface FavoriteColorWidgetUiBinder extends
               UiBinder<widget, FavoriteColorWidget> {
     }
 
     @UiField Label greeting;
     @UiField CheckBox red;
     @UiField CheckBox white;
     @UiField CheckBox blue;
     @UiField Button button;
 
     public FavoriteColorWidget() {
          initWidget(uiBinder.createAndBindUi(this));
 
          // add a greeting
          greeting.setText("Hello Jeff!!");
 
          final ArrayList<checkBox> checkboxes = new ArrayList<checkBox>();
          checkboxes.add(red);
          checkboxes.add(white);
          checkboxes.add(blue);
 
         // add a button handler to show the color when clicked
          button.addClickHandler(new ClickHandler() {
               public void onClick(ClickEvent event) {
                    String t = "";
                    for(CheckBox box : checkboxes) {
                         // if the box was checked
                         if (box.getValue()) {
                              t += box.getFormValue() + ", ";
                         }
                    }
                    Window.alert("Your favorite color/colors are: "+ t);
               }
          });
 
     }
 
}
The last thing we’ll need to do is add our new widget to the MyBinderWidget template. Open MyBinderWidget.ui.xml and add the custom namespace reference and the FavoriteColorWidget.
1
2
3
4
5
6
7
8
9
10
11
12
13
<!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.jeffdouglas.client">
     <ui:style>
          .bolder { font-weight:bold; }
     </ui:style>
     <g:HTMLPanel>
          <g:Label styleName="{style.bolder}" text="This is my label in bold!"/>
          <g:VerticalPanel ui:field="myPanelContent" spacing="5"/>
          <c:FavoriteColorWidget/>
     </g:HTMLPanel>
</ui:UiBinder>
Now when you run the application it should look like the following.