Archive for January, 2012

16
Jan
12

Invoke Server Side Code Using GWT

This page describes how to Invoke Server Side Code to retrieve data from the server side and display the results in a JavaScript pop-up.

Background

GWT generates JavaScript code that makes a call to server side components thru the Servlet Interface. The Service Implementation class extends the “RemoteServiceServlet” class. This allows GWT to respond to requests made from the GWT generated Javascript.

Requirements

Procedure

Before we begin we need to create directories.

mkdir -p src/main/java/com/test/server

Create the Interface

First you create a an interface that can be used by the client. Maven generates a client side Interface based this.

vi src/main/java/com/test/client/GreetingService.java

package com.test.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("greet")
public interface GreetingService extends RemoteService {
  String greetServer(String input) throws IllegalArgumentException;
}

Create the Implementation

vi src/main/java/com/test/server/GreetingServiceImpl.java

package com.test.server;

import com.test.client.GreetingService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
    GreetingService {

  public String greetServer(String input) throws IllegalArgumentException {
    String serverInfo = getServletContext().getServerInfo();
    String userAgent = getThreadLocalRequest().getHeader("User-Agent");

    return "Hello, " + input + "! I am running " + serverInfo
        + ".It looks like you are using:" + userAgent;
  }
}

Define the Servlet

Add the servlet to the web.xml.

vi src/main/webapp/WEB-INF/web.xml

  <!-- Servlets -->
  <servlet>
    <servlet-name>greetServlet</servlet-name>
    <servlet-class>com.test.server.GreetingServiceImpl</servlet-class>
  </servlet>

  <!-- Servlet-Mapping -->
  <servlet-mapping>
    <servlet-name>greetServlet</servlet-name>
    <url-pattern>/matrix/greet</url-pattern>
  </servlet-mapping>

Change the EntryPoint

Make the changes described in the following patch file by hand to the existing file.

vi src/main/java/com/test/client/Matrix.java

--- src/main/java/com/test/client/Matrix.java
+++ src/main/java/com/test/client/Matrix.java	
@@ -5,15 +5,26 @@
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.RootPanel;
 
 public class Matrix implements EntryPoint {
-
+	private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
+	
 	public void onModuleLoad() {
 		Button button = new Button("Send", new ClickHandler() {
 			public void onClick(ClickEvent event) {
-				Window.alert("Hello World!");
+		        greetingService.greetServer("World", new AsyncCallback<String>() {
+		            public void onFailure(Throwable caught) {
+		              // Show the RPC error message to the user
+		              Window.alert("Remote Procedure Call - Failure");
+		            }
+
+		            public void onSuccess(String result) {
+		                Window.alert(result);
+		            }
+		          });
 			}
 		});
 		button.setStyleName("sendButton");

Test the application

mvn compile gwt:run

After clicking the button on the screen a JavaScript alert box will open returning text from the server side. You can use Firefox FireBug plugin to verify the server side communication.

16
Jan
12

Internationalizing a GWT Application

This page describes how to setup internationalization in your GWT application. The example on this page builds from the application described here.

Requirements

Project Configuration

In order to enable internationalization support you need to add the following “goal” and “i18nMessagesBundle” elements inside “gwt-maven-plugin”:

vi pom.xml

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>gwt-maven-plugin</artifactId>
        <version>2.4.0</version>
        <executions>
          <execution>
            <goals>
            ...
            <goal>i18n</goal>
            ...
            </goals>
...

insert the “i18nMessagesBundle” element here:

        <configuration>
          ...
          <i18nMessagesBundles>
                    <i18nMessagesBundle>com.test.client.Messages</i18nMessagesBundle>
          </i18nMessagesBundles>
          ...
        <configuration>

Externalize the language strings to a property file.

The following message bundle is converted to a Java Class by Maven. In order to specify additional bundles just insert an additional “i18nMessagesBundle” tag in the pom.xml file.

Properties File

Create the directory that will hold the property file if not done so already:

mkdir -p src/main/resources/com/test/client

vi src/main/resources/com/test/client/Messages.properties

sendButton = Send
hello = Hello {0}!

Java code Change

Modify the java code to reference the property values instead of hard-coded strings.

--- matrix-blank/src/main/java/com/test/client/Matrix.java	
+++ matrix/src/main/java/com/test/client/Matrix.java	
@@ -10,10 +10,11 @@
 
 public class Matrix implements EntryPoint {
 
+	private final Messages messages = GWT.create(Messages.class);
 	public void onModuleLoad() {
-		Button button = new Button("Send", new ClickHandler() {
+		Button button = new Button(messages.sendButton(), new ClickHandler() {
 			public void onClick(ClickEvent event) {
-				Window.alert("Hello World!");
+				Window.alert(messages.hello("World"));
 			}
 		});
 		button.setStyleName("sendButton");

Test the Change

mvn compile gwt:run

The French Version

Creating a French version of the application is simple!. Just Create a copy of the file and append an _fr or the locale you want to support.

cp src/main/resources/com/test/client/Messages.properties \
src/main/resources/com/test/client/Messages_fr.properties

Modify the file and update the English to French.

vi src/main/resources/com/test/client/Messages_fr.properties

sendButton = Envoyer
hello = bonjour {0}!

Configure

You can add the following line into the module element of your “gwt.xml” file for each locale you want to support:
vi src/main/resources/com/test/Matrix.gwt.xml

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

Start the application

mvn compile gwt:run

Test the Change

At this point you have 2 options to see the French version of the site:

  1. You can put the following line in the host HTML page
    <meta name="gwt:property" content="locale=fr">
    

  2. Append the client property value to the query string of the URL: http://127.0.0.1:8888/Matrix.html?gwt.codesvr=127.0.0.1:9997?locale=fr

Either way you will see the French version of the site.

Reference

http://code.google.com/webtoolkit/doc/latest/tutorial/i18n.html

Appendix

Creating Keys for place holder parameters, the lines of the property file should look like this:

myString = First parm is {0}, second parm is {1}, third parm is {2}.

The key “myString” can be used in static HTML by wrapping the content with a html tag with an assigned id.

    <h1 id="myString"></h1>

The id attribute can be used as a handle to replace the text in Java code like this:

    RootPanel.get("appTitle").add(new Label(constants.myString("one","two","three")));

To get the list of locale’s supported by your JVM just run the following code:

	public static void main(String args[]) {
		Locale locales[] = SimpleDateFormat.getAvailableLocales();
		List arrayList = Arrays.asList(locales);
		Collections.sort(arrayList, new Comparator() {
			public int compare(Locale o1, Locale o2) {
				return o1.getDisplayName().compareTo(o2.getDisplayName());
			}
		});
		for (Locale locale : arrayList) {
			System.out.println(locale.toString() + "\t" + locale.getDisplayName());
		}
	}

14
Jan
12

Blank GWT Template Starter Application

This page describes the complete end-to-end process of creating and testing a blank “Hello World” type Google Web Tool kit (GWT) starter application using Maven. The page takes about 10-15 minutes to complete and have a working GWT application.

The application described on this page displays a Send Button on the page. It displays a JavaScript alert() message when the button is clicked.

Background

The GWT SDK allows you to generate an application using their generation tool. However I never liked using this tool because the application it generated is useless to me unless I understand how the application is working. The following page breaks down a simple Hello World GWT application step by step and allows the reader to follow along.

Requirements

  • Maven
  • Java 5 or above

This page covers GWT version 2.4.0.

The first step is to create directory that will hold your project. The example below uses “matrix” as the project name. You can replace each instance of “matrix” with whatever you want to call your project.

mkdir matrix
cd matrix
# create some additional directories
mkdir -p src/main/java/com/test/client
mkdir -p src/main/resources/com/test
mkdir -p src/main/webapp/WEB-INF

vi pom.xml

<?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">

  <!-- POM file generated with GWT webAppCreator -->
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>matrix</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>GWT Maven Archetype</name>

  <properties>
    <!-- Convenience property to set the GWT version -->
    <gwtVersion>2.4.0</gwtVersion>
    <!-- GWT needs at least java 1.5 -->
    <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-servlet</artifactId>
      <version>${gwtVersion}</version>
      <scope>runtime</scope>
    </dependency>
    <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>
  </dependencies>

  <build>
    <!-- Generate compiled stuff in the folder used for developing mode -->
    <outputDirectory>${webappDirectory}/WEB-INF/classes</outputDirectory>
    <plugins>
      <!-- GWT Maven Plugin -->
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>gwt-maven-plugin</artifactId>
        <version>2.4.0</version>
        <executions>
          <execution>
            <goals>
              <goal>compile</goal>
              <goal>test</goal>
              <goal>generateAsync</goal>
            </goals>
          </execution>
        </executions>
        <!-- Plugin configuration. There are many available options, see 
          gwt-maven-plugin documentation at codehaus.org -->
        <configuration>
          <runTarget>Matrix.html</runTarget>
          <hostedWebapp>${webappDirectory}</hostedWebapp>
        </configuration>
      </plugin>

      <!-- Copy static web files before executing gwt:run -->
      <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.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Host HTML Page

The following is the Host HTML Page. The page imports the generated Javascript and starts the Javascript application. Similar to the “Entry Point” main() method of many other programming languages.

vi src/main/webapp/Matrix.html

<!doctype html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="Matrix.css">
    <title>X</title>
    <script type="text/javascript" language="javascript" src="matrix/matrix.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>
    <div id="sendButtonContainer"></div>
  </body>
</html>

CSS Styles

GWT components are highly customizable. It makes sense to define sizes, colors, alighment, images, and other visual aspects of the component in CSS.

vi src/main/webapp/Matrix.css

.sendButton {
  display: block;
  font-size: 12pt;
}

Web Application Descriptor

The following is a basic web.xml file for the application.

vi src/main/webapp/WEB-INF/web.xml

<?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-Mapping -->

  <!-- Default page to serve -->
  <welcome-file-list>
    <welcome-file>Matrix.html</welcome-file>
  </welcome-file-list>
</web-app>

vi src/main/resources/com/test/Matrix.gwt.xml

<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='matrix'>
  <inherits name='com.google.gwt.user.User' />
  <inherits name='com.google.gwt.user.theme.standard.Standard' />
  <entry-point class='com.test.client.Matrix' />
  <source path='client' />
</module>

vi src/main/java/com/test/client/Matrix.java

package com.test.client;

import com.google.gwt.core.client.EntryPoint;
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.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;

public class Matrix implements EntryPoint {

	public void onModuleLoad() {
		Button button = new Button("Send", new ClickHandler() {
			public void onClick(ClickEvent event) {
				Window.alert("Hello World!");
			}
		});
		button.setStyleName("sendButton");
		RootPanel.get("sendButtonContainer").add(button);
	}
}

Run the project

mvn eclipse:clean eclipse:eclipse
mvn clean compile gwt:run

What’s Next?




Follow

Get every new post delivered to your Inbox.

Join 34 other followers