Archive

Archive for the ‘GWT’ Category

Super Dev Mode with GWT 2.5.1-rc1 and Chrome 26.0

April 13th, 2013 No comments

Here are the steps to run the super dev mode which is a new feature of GWT 2.5.
The versions i used are GWT 2.5.1-rc1 and Chrome 26.0. That version of Chrome requires the latest version of GWT, otherwise it will not work. I tested it with GWT 2.5 previously and I could not see the source code in Chrome browser.

  • Step 1 :

Modify the module.gwt.xml file to add these lines :


<add-linker name="xsiframe"/>
<set-configuration-property name="devModeRedirectEnabled" value="true"/>

  • Step 2 :

Compile your code as you usually do : mvn install

  • Step 3 :

Launch the super dev mode. That can easily be done with the gwt-maven-plugin plugin and the goal run-codeserver :

SuperDevMode

The following lines appear at the end of the console in Eclipse :

[INFO] The code server is ready.
[INFO] Next, visit: http://localhost:9876/
  • Step 4 :

Open the URL http://localhost:9876/ in Chrome :

GWTCodeServerChrome

And do as it says : create 2 bookmarks in Chrome for Dev Mode On and Dev Mode Off, with the help of the bookmarklets. Which I have already done.
Then run the application.
Since I did not use an external server, I ran the application in development mode (gwt:run) so it runs with Jetty. But i could have run it directly under WebLogic for instance.
Then go to the URL of the application :
http://127.0.0.1:8888/PlanetEarth.html?gwt.codesvr=127.0.0.1:9997
In fact remove the “?gwt.codesvr=127.0.0.1:9997″ part of the URL. It is no longer necessary to install the Google Web Toolkit Developer Plugin for the browser. So the URL to go to is http://127.0.0.1:8888/PlanetEarth.html :

SuperDevModeChrome1

  • Step 5 :

While on that page, click on the “Dev Mode On” bookmark. A popup asking to compile the module will show up :

SuperDevModeChrome2

Click on Compile. This will recompile the application.
Then in Chrome go to Tools > Developers Tools > Settings and check the checkbox “Enable source maps” :

SuperDevModeChrome3

Refresh the page and you should see the Java code in the “Sources” tab :

SuperDevModeChrome4

You can then directly debug in Chrome by adding breakpoints :

SuperDevModeChrome5

Link :
https://developers.google.com/web-toolkit/articles/superdevmode

Categories: GWT Tags:

[GWT] How to print a widget or a page

January 30th, 2013 No comments

To print a widget or an entire page with GWT, you can use JSNI and the JavaScript print function.

A good practice is to put all the content you want to print inside a DIV tag, for instance :

<!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:p1="urn:import:com.mycompany.gwtproject.client.common.ui.composite">
	<ui:style>
		/* Add CSS here. See the GWT docs on UI Binder for more details */
		.important {
			font-weight: bold;
		}
	</ui:style>
...
<div id="printAll">
	<g:Label text="Some title" styleName="pageTitle" />		
	<div style="height:30px"></div>
		<p1:DetailAgency ui:field="detailAgency " />
	<div style="height:30px"></div>
		<p1:DetailCountry ui:field="detailCountry" />
	<div style="height:15px"></div>
</div>
<div style="float:left;margin-right:20px">
		<g:Button text="Print" ui:field="printBtn" />
</div>

An id is assigned to that DIV tag (line 10) and a button is added to the page. It calls the Java print method from the Print class:


import com.mycompany.gwtproject.client.service.print.Print;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
...

public class MyViewImpl extends Composite implements MyView {
...
@UiField
Button printBtn;

@UiHandler("printBtn")
void onPrintBtnClick(ClickEvent event) {
	Element element = DOM.getElementById("printAll");
	Print.it(element);
}

This class Print.java contains several methods it that help you print the window, a widget, etc. In the end, they call the JavaScript print() function :

...
public static native void printFrame() /*-{
        var frame = $doc.getElementById('__printingFrame');
        frame = frame.contentWindow;
        frame.focus();
        frame.print();
    }-*/;
...

You can apply CSS to the printed page. If you work with uiBinder and want to print a widget that has no id defined in the XML template, you can assign one in the corresponding Java class :

...
<g:VerticalPanel ui:field="myDetails">
	<p1:DetailAgency ui:field="detailAgency " />
	<p1:DetailCountry ui:field="detailCountry " />
</g:VerticalPanel>
...

import com.mycompany.gwtproject.client.service.print.Print;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
...

public class MyView2Impl extends Composite implements MyView2 {

@UiField
VerticalPanel myDetails;

@UiHandler("printBtn")
void onPrintBtnClick(ClickEvent event) {
	printBtn.getElement().setId("details");
	Element element = DOM.getElementById("details");
	Print.it(element);
}

This will fire the print window :
Print

Links :
http://code.google.com/p/gwt-print-it/source/browse/trunk/src/br/com/freller/tool/client/Print.java

Categories: GWT, Java Tags:

[Book review] Programmation GWT 2, second edition

January 6th, 2013 No comments

Here is my book review of the second edition of the book Programmation GWT 2 (author : Sami Jaber). In French since the book is written in French.

Cette deuxième édition fait 21 chapitres (516 pages) alors que la première édition comptait 17 chapitres (461 pages). Soit environ 50 pages supplémentaires.
Elle prend en compte les nouveautés introduites depuis la version 2.0 jusqu’à la version 2.5.
Les développeurs francophones peuvent certainement remercier l’auteur d’avoir mis à leur disposition un livre en français qui est aussi complet et à jour sur GWT.

Chapitre 1
Le premier chapitre présente clairement la structure d’un projet GWT mais aussi les différents modes : mode développement et mode production. Avec une petite introduction à une nouveauté de la version 2.5 : le super DevMode.

Chapitres 2 et 3
Dans le chapitre 2, j’ai apprécié l’honnêteté de l’auteur qui souligne dès le début “la simplicité et la sobriété” des widgets disponibles en standard dans le framework. Les principaux widgets sont passés en revue, avec exemples d’utilisation à l’appui (code Java et CSS, ainsi que des captures d’écran).

Chapitre 4
Je pense que ce chapitre dresse un bon tour d’horizon des bibliothèques tierces (Sencha Ext-GWT, SmartGWT, GWT-DnD, GChart, GWT HighCharts) et des frameworks complémentaires (Vaadin entre autres).

Chapitre 5
L’utilisation de JavaScript dans du code Java est étudiée de façon minutieuse dans ce chapitre : insertion de code JavaScript dans une méthode Java, intégration d’un fichier JavaScript externe, correspondance des types entre Java et JavaScript, etc. L’auteur fournit également des explications sur les types Overlay, plutôt méconnus.

Chapitre 6
La création de composants personnalisés est souvent nécessaire dans un projet et ce livre ne manque pas d’y consacrer un chapitre entier. On y voit de façon détaillée la mécanique événementielle de GWT et le modèle de widget.

Chapitre 7
Ce chapitre décrit les services RPC et dévoile les bonnes pratiques à mettre en place lors de leurs utilisations.

Chapitre 8
Ce chapitre met l’accent sur l’intégration J2EE avec un exemple d’utilisation des EBJ 3 et de JPA. J’ai trouvé l’exemple pertinent et suffisamment illustré par du code.

Chapitres 9, 10 et 11
Ces chapitres expliquent et décrivent amplement le chargement à la demande (code splitting), la liaison différée (deferred binding) et la gestion des ressources (API ClientBundle) à grand renfort de code, de rapports de compilation, de captures d’écran de navigateurs, etc.

Chapitre 12
Ce chapitre rentre dans les entrailles de GWT : différentes facettes du compilateur, fichiers créés, réduction de code (pruning) et optimisations.

Chapitre 13
Le mécanisme de l’internationalisation avec GWT est traité dans ce chapitre. L’auteur aborde et montre bien l’utilisation de l’API i18n, les dictionnaires, les messages, les conversions de types ainsi que l’outillage.

Chapitre 14
Les tests ne sont pas délaissés puisqu’un chapitre entier y est dédié. On y voit l’utilisation de GWTTestCase, HTMLUnit et Selenium. Ce dernier framework est pas mal utilisé dans le chapitre, notamment pour l’écriture des tests fonctionnels (description de Selenium IDE et du module WebDriver). Enfin la notion de mocking n’est pas oubliée puisqu’elle est illustrée avec un exemple utilisant JMock et EasyMock.

Chapitre 15
Ce chapitre sur les design patterns est à mon avis un des plus importants car il liste les bonnes pratiques d’architecture et de conception. Et à mon avis l’auteur a fait un très bon travail en fournissant pas mal de conseils : comment gérer la session, l’historique du navigateur, les traitements longs avec les classes Timer et Scheduler, les patterns Commande, MVC et MVP, etc.

Chapitre 16
J’ai trouvé le chapitre dédié à UIBinder très exhaustif. On y voit la gestion des styles et ressources, l’incorporation des images, la gestion des évènements, le référencement de widgets composites à l’intérieur d’un widget composite…

Chapitre 17
Un très court chapitre qui prend la peine de faire un tour d’horizon du plug-in Eclipse pour GWT. Je pense qu’il montre bien ses possibilités.

Chapitre 18
Un chapitre est consacré aux composants CellWidget. J’ai bien apprécié la description et l’utilisation (nombreux extraits de code) du widget CellTable, très utilisé pour la création de tableaux. La documentation officielle de Google est très bonne sur le sujet mais des explications supplémentaires et de surcroît en français ne sont jamais de trop !

Chapitre 19
Enfin un chapitre dédié à l’API Activities and Places. À l’heure actuelle il existe encore peu d’ouvrages qui abordent en détail cette API et c’est un gros manque. Dans ce chapitre l’auteur explique longuement cette API complexe et l’illustre à l’aide d’un exemple et d’un schéma décrivant toute la chaîne d’exécution de l’API Activities and Places.

Chapitres 20 et 21
Ces deux derniers chapitres concernent les API RequestFactory, AutoBean et Editors. Tous les deux sont bien riches en code, explications, conseils et avertissements !

De manière générale j’ai beaucoup apprécié l’exhaustivité des explications fournies dans la plupart des chapitres. Mais aussi les conseils et avertissements sur certains sujets complexes.
J’ai aussi beaucoup apprécié l’apparition d’un chapitre entièrement dédié à Activities and Places. L’importance de ce framework dans le développement d’une application GWT mérite en effet un chapitre à lui tout seul et l’auteur a bien veillé à en inclure un mais a également produit un bel effort d’explications détaillées de cette API difficile pour la rendre plus compréhensible et plus assimilable.
Je n’ai a posteriori noté qu’un seul manque dans ce livre : une présentation un peu plus détaillée du super dev mode, qu’on avait annoncé comme une nouveauté très intéressante de la version 2.5. Mais cette fonctionnalité est relativement neuve, notamment au moment de l’écriture de cette deuxième édition du livre.

Sommaire

Introduction à GWT
Chapitre 1 : L’environnement de développement
Chapitre 2 : Les contrôles
Chapitre 3 : Le modèle de placement CSS
Chapitre 4 : Les bibliothèques tierces
Chapitre 5 : L’intégration de code JavaScript
Chapitre 6 : La création de composants personnalisés
Chapitre 7 : Les services RPC
Chapitre 8 : L’intégration J2EE
Chapitre 9 : Le chargement à la demande
Chapitre 10 : La liaison différée
Chapitre 11 : La gestion des ressources
Chapitre 12 : Sous le capot de GWT
Chapitre 13 : L’internationalisation
Chapitre 14 : L’environnement de tests
Chapitre 15 : Les design patterns GWT
Chapitre 16 : La création d’interfaces avec UIBinder
Chapitre 17 : Le plug-in Eclipse pour GWT
Chapitre 18 : Les composants CellWidget
Chapitre 19 : Activités et places
Chapitre 20 : L’API Request Factory
Chapitre 21 : L’API Editors

Categories: Book reviews, GWT Tags:

The future of GWT 2012 Report

December 13th, 2012 No comments

And here is the report :
https://vaadin.com/gwt/report-2012/

1300 respondents who answered 30 questions. The report is 20 pages and full of data, charts, stats and commentaries !

Here are some conclusions from the report :

  • compile time and widgets quality are the worst features of GWT
  • cross browser compatibility is the favorite feature
  • size of the uncompressed obfuscated JavaScript is mostly between 2M and 10M
  • most popular framework/API to use the MVP pattern is GWT 2.4 Activities and Places
  • backend communication is mainly done with GWT RPC
Categories: GWT, JavaScript, MVP Tags:

The future of GWT survey

September 19th, 2012 No comments

I want to relay this interesting survey from the GWT Steering Committee (and Vaadin).
You can take it here :

https://vaadin.com/blog/-/blogs/the-future-of-gwt-survey

Categories: GWT Tags:

My presentation of GWT 2.4

June 6th, 2012 No comments

I have recently done a presentation of GWT 2.4
It is now available on slideshare.net :

I might work on it again later. To make it a bit nicer.

Categories: Architecture, Eclipse, GWT, Java, Maven, MVP Tags:

How to launch the hosted mode with Jonas and Maven

April 23rd, 2012 No comments

GWT uses an embedded Jetty server. It is used at the beginning of the development of an application. During the prototype phase.
Personally, I used it for about a year, until we got the need to use JMS.
And since Jetty is not a Java EE server – it does not implement the JMS API – it was time to say goodbye to Jetty and use the application server that is used in production : Jonas.
There is not much info about the configuration to use in order to launch the hosted mode with a server different from Jetty. I found that the official website of the gwt-maven-plugin lacks information in that area.

I spent a few hours finding out the correct configuration for that. So here is how to do it :
1) Start Jonas
2) Deploy the application (EAR or WAR)
3) Run the goal gwt:run

And the configuration for the gwt-maven-plugin plugin is the following :


<plugins>
  <plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>gwt-maven-plugin</artifactId>		
					
	<!-- Old configuration, to run the hosted mode with JETTY. -->
	<!-- 
		<configuration>
		<runTarget>identify.html</runTarget>
		<hostedWebapp>${project.build.directory}/${project.build.finalName}</hostedWebapp>
		<modules>
			<module>${project.groupId}.foo.bla.MainApplication</module>
			<module>${project.groupId}.foo.bla.SecondEntry</module>
		</modules>
		<copyWebapp>true</copyWebapp>										
		<extraJvmArgs>-XX:MaxPermSize=512M  -Xms512M -Xmx1024M </extraJvmArgs>
	</configuration>
	 -->
	
	<!-- New configuration, to run the hosted mode with JONAS -->
	<configuration>					
		<modules>
			<module>${project.groupId}.foo.bla.MainApplication</module>
			<module>${project.groupId}.foo.bla.SecondEntry</module>
		</modules>					
		<extraJvmArgs>-XX:MaxPermSize=512M  -Xms512M -Xmx1024M </extraJvmArgs>
		
		<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory> 
		<runTarget>http://localhost:9000/app-context/main.html</runTarget> 
		<copyWebapp>false</copyWebapp> 
		<!--  do not start JETTY -->
		<noServer>true</noServer>
		<!-- the folder where the exploded WAR is located, inside Jonas -->
		 <!--  Constant path if jonas.development=false in conf/jonas.properties --> 					
		<hostedWebapp>${env.JONAS_BASE}\work\webapps\jonas\ear\myapp-ear-SNAPSHOT.ear\${project.build.finalName}.war</hostedWebapp>
		<bindAddress>localhost</bindAddress>   <!--  other possible value : 0.0.0.0 -->
		<logLevel>INFO</logLevel> 
		<style>OBF</style> 			
	</configuration>
	<executions>
		<execution>
			<id>gwtcompile</id>
			<phase>prepare-package</phase>
			<goals>
				<goal>compile</goal>
			</goals>
		</execution>
	</executions>
   </plugin>
...
</plugins>			

Line 35 is the most important : it specifies the path where the exploded war is deployed in Jonas.
That configuration could work with another application server of course.

Categories: GWT, JOnAS, Maven Tags:

Securing a GWT application with AOP

March 12th, 2012 No comments

AOP can be a good solution to protect the business methods in an application developed with (or without) GWT.
If we have a method called displayCustomerData(…) and we want to make sure only a certain category of users can call it, for instance the category MANAGER, then AOP can come to the rescue.

I used AspectJ and Spring AOP to implement that. One should not be surprised to notice a tight integration of AOP in Spring since the spec lead for AspectJ is Adrian Coyler, who is also one of the main Spring committers.

0) First, add the needed dependencies with Maven :

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aop</artifactId>
	<version>3.0.6.RELEASE</version>
</dependency>

<!-- ASPECTJ dependencies -->
<!-- ******************** -->			
<dependency>
	<groupId>org.aspectj</groupId> 
	<artifactId>aspectjrt</artifactId>
	<version>1.6.12</version> 
</dependency>
							
<dependency>
	<groupId>aspectj</groupId>
	<artifactId>aspectjweaver</artifactId>
	<version>1.5.4</version>
</dependency>	

1) Then create your own annotation

package com.myproject.aop;
import java.io.Serializable;

public enum RoleEnumDto implements Serializable {
	MANAGER, SUPERVISER, BASIC_USER;
}

package com.myproject.aop;
import java.io.Serializable;

@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD })
@Inherited
public @interface AuthorizedRoles {

	RoleEnumDto[] value();
}


2) Then add the AspectJ and Spring dependencies


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans   

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd


http://www.springframework.org/schema/aop

       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">	
	
	<!-- Enable the @AspectJ support. -->
	<aop:aspectj-autoproxy/>

	<bean id="checkAuthorizedRoles" class="com.myproject.aop.CheckAuthorizedRoleAspect"   />

</beans>

3) Then develop the aspect, which is a class annotated with @Aspect.


package com.myproject.aop;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


@Order(0)
@Aspect
public class CheckAuthorizedRoleAspect {
	
private static final Logger log = Logger.getLogger(CheckAuthorizedRoleAspect.class);
	
/**
 * The pointcut expression where to bind the advice
 */
@Pointcut("  @annotation(com.myproject.AuthorizedRoles)")
private void businessMethods() {		
	log.debug("Entering businessMethods()");		
}// the pointcut signature
	
	
 @Before("businessMethods()")
 public void checkAuthorizedAdvice(JoinPoint joinPoint, AuthorizedRoles authorizedRoles) throws    ForbiddenAccessException {
  log.debug("Entering checkAuthorizedAdvice()");
  log.debug(joinPoint.getSignature().getName());

  // Do some role checking 
  // 1. Proceed the method if the user has the required role
  if (...) {
          return pjp.proceed();
  //2. Throw an exception if not.
  else {
  throw new ForbiddenAccessException ("The user is not allowed to call this method");
  }
 }
	 		 
}

The @Order(0) annotation is useful in the case where a jointpoint can be intercepted by several aspects.
The annotation AuthorizedRoles is passed as a parameter to the checkAuthorizedAdvice(…) method, which is the advice.
The pointcut expression matches all methods annotated with the AuthorizedRoles annotation.

4) Finally, add the annotation to the business method you want to restrict the access to. This business method can be called by the implementation of an RPC service for instance :


@Override
@Transactional(rollbackFor = SomeException.class)
@AuthorizedRoles( { RoleEnumDto.MANAGER, RoleEnumDto.SUPERVISER })
public Customer displayCustomerData(long id) throws NotFoundException {
		...
}

Pretty easy and pretty powerful.

Categories: AOP, AspectJ, GWT, Spring, Spring AOP Tags:

Handling form-based file upload with GWT and the Apache Jakarta Commons FileUpload library

November 27th, 2011 No comments

Uploading files to a filesystem, a remote server, a database, etc, is a frequent need in web applications.
These files are often multipart data (that is of varying types such as XML, HTML, plain text, binary … ).
With GWT, a good solution to handle this need is the use of the Apache Jakarta Commons FileUpload library.

First, generate a skeleton project using the gwt-maven-plugin archetype :

mvn archetype:generate  

Choose archetype number 298 which makes use of the gwt-maven-plugin and generates a simple hello world sample.

298: remote -> gwt-maven-plugin (Maven plugin for the Google Web Toolkit.)

You can easily import that project into Eclipse (File > Import …> Maven > Existing Maven projects).

Add the following dependency to the pom.xml file:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.2.2</version>
</dependency>

In the client side, modify the onModuleLoad() method of the entry point class (called Firstmodule.java in my project) and add the following code at the end :

package com.mycompany.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.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.mycompany.shared.FieldVerifier;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Firstmodule implements EntryPoint {
...
 /**
   * This is the entry point method.
   */
  public void onModuleLoad() {
...
 final FormPanel form = new FormPanel();	  
    VerticalPanel vPanel = new VerticalPanel(); 
    // http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/user/client/ui/FileUpload.html
    form.setMethod(FormPanel.METHOD_POST);
    //The HTTP request is encoded in multipart format. 
    form.setEncoding(FormPanel.ENCODING_MULTIPART); //  multipart MIME encoding
    form.setAction("/FileUploadGreeting"); // The servlet FileUploadGreeting
    
    form.setWidget(vPanel);
    
    FileUpload fileUpload = new FileUpload();
    fileUpload.setName("uploader"); // Very important    
    vPanel.add(fileUpload);    
    
    Label maxUpload =new Label();
    maxUpload.setText("Maximum upload file size: 1MB");
    vPanel.add(maxUpload);
        
    vPanel.add(new Button("Submit", new ClickHandler() {
        public void onClick(ClickEvent event) {
                form.submit();
        }
    }));
    
    RootPanel.get("uploadContainer").add(form); 
...
}     
}

You need to add the FileUpload widget inside a FormPanel widget. Set the action (servlet) that will be called when the user submits the form.
Line 43 is very important. You need to set a name to the FileUpload widget, otherwise the upload will not work. In fact, all of the fields under the FormPanel that you want to use need to have a name so that the HttpServlet can identify them.
The HTTP request is encoded in multipart format (line 37).
The generated HTML code will contain the following line :

<form action="FileUploadGreeting" method="POST" enctype="multipart/form-data">

In the server side, create the servlet that will be called when the user clicks on the Submit button :

package com.mycompany.server.form;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadFileHandler extends HttpServlet {
	
	private static final long serialVersionUID = 1L;
	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
			
	 System.out.println("Inside doPost");		
		
		// Create a factory for disk-based file items
		FileItemFactory factory = new DiskFileItemFactory();
		// Create a new file upload handler
		ServletFileUpload fileUpload  = new ServletFileUpload(factory);
		// sizeMax - The maximum allowed size, in bytes. The default value of -1 indicates, that there is no limit.
		// 1048576 bytes = 1024 Kilobytes = 1 Megabyte
		fileUpload.setSizeMax(1048576);  
		
		if (!ServletFileUpload.isMultipartContent(request)) {
		      try {
		    	
				throw new FileUploadException("error multipart request not found");
			} catch (FileUploadException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		 		  		
		try {

			List<FileItem> items = fileUpload.parseRequest(request);
			
			if (items == null) {			
                response.getWriter().write("File not correctly uploaded");
                return;
          }
			
			Iterator<FileItem> iter = items.iterator();

			while (iter.hasNext()) {
				FileItem item = (FileItem) iter.next();
				
				////////////////////////////////////////////////
				// http://commons.apache.org/fileupload/using.html								
				////////////////////////////////////////////////

				//if (item.isFormField()) {															
					String fileName = item.getName();
					System.out.println("fileName is : " + fileName);	
					String typeMime = item.getContentType();
					System.out.println("typeMime is : " + typeMime);	
					int sizeInBytes = (int) item.getSize();
					System.out.println("Size in bytes is : " + sizeInBytes);	
					//byte[] file = item.get();					
					item.write(new File("fileOutput.txt"));		        							
				//}
			}
			
			PrintWriter out = response.getWriter();
			response.setHeader("Content-Type", "text/html");
			out.println("Upload OK");
			out.flush();
			out.close();

		} catch (SizeLimitExceededException e) {
			System.out.println("File size exceeds the limit : 1 MB!!" );			
		} catch (Exception e) {
			e.printStackTrace();
			PrintWriter out = response.getWriter();
			response.setHeader("Content-Type", "text/html");
			out.println("Error");
			out.flush();
			out.close();
		}
		
	}
	
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

}

You can easily set a size limit for uploaded files (line 36). An SizeLimitExceededException exception is raised if the size exceeds the limit (line 84).
The parseRequest(…) method, line 50, returns the list of items that were submitted.
The method isFormField() determines whether or not an item is a plain form field, as opposed to a file upload. I have commented it out at line 66 because the form only contains one field, which is the uploaded file.
You can also easily get information about the uploaded file (name, size, typeMime).
In the end, i simply write the uploaded file into a new file called fileOutput.txt which is saved at the root of the project.

Update the deployment descriptor file to declare the servlet and map it to an URL:

 <!-- Upload -->
	<servlet>
		<servlet-name>FileUploadGreeting</servlet-name>
		<servlet-class>com.mycompany.server.form.UploadFileHandler</servlet-class>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>FileUploadGreeting</servlet-name>
		<url-pattern>/FileUploadGreeting</url-pattern>
	</servlet-mapping>

Finally compile and run the project in GWT Development Mode. Right-click anywhere in the Project Explorer and choose “Run As -> Maven Build…” and run the “gwt:run” goal:

Here is a screenshot of the page with the FileUpload widget added:

The whole code is available on GitHub : https://github.com/longbeach/GWTCommonsFileUpload

Links :
http://www.ietf.org/rfc/rfc1867.txt

Categories: Git, GWT, Maven, RIA and RDA, SCM Tags:

[GWT] Reduce the number of permutations

May 31st, 2011 No comments

Here is a tip that I found on other blogs and I think is worth mentioning again. I tried it, it reduced the number of permutations from 15 to 3 only (1 permutation for IE, 1 permutation for the FR locale, 1 permutation for the EN locale). That means a compilation time of 1:05.750s instead of 2:02.828s.

In the module file (blabla.gwt.xml), you need to add this line :

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

This of course will produce permutations for Internet Explorer 6 only.
There is also another property to define the locales :

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

So this will generate 2 permutations only : 1 for IE and 1 for the FR locale.

Here is a list of user agents :
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/UserAgent.gwt.xml

Categories: GWT Tags:

[GWT] Table with pagination and one sortable column

April 10th, 2011 No comments

I just added a very basic GWT project to my github account to display a table with pagination and one sortable column.
The code is mostly based on the official GWT tutorial :
http://code.google.com/intl/en/webtoolkit/doc/latest/DevGuideUiCellTable.html

I basically just added the SimplePage element to handle pagination :

SimplePager pager = new SimplePager();
pager.setDisplay(table);

Source :
https://github.com/longbeach/MyFirstCellTable
Demo :
http://tableaupagination.appspot.com/

Categories: Git, Google App Engine, GWT, SCM Tags:

How to rollback a transaction in GAE

April 10th, 2011 No comments

This has nothing to do with JPA.
I was trying to deploy a GWT webapp to GAE when I suddenly got an error.
As a remedy, i got the message :
"java.io.IOException: Error posting to URL: https://appengine.google.com/api/appversion/create?app_id=tableaupagination&version=2&
409 Conflict
Another transaction by user xxxxx is already in progress for this app and major version. That user can undo the transaction with appcfg.py's "rollback" command."

After digging into Google a bit, I found that the way to launch that rollback command under Windows is the following :
1) Figure out where the Google App Engine Java SDK directory is.
In my case, it’s under the Eclipse plugins directory :
D:\Dev\eclipse-jee-helios-SR1-win32\plugins\com.google.appengine.eclipse.sdkbundle.1.4.2_1.4.2.v201102111811

The bin folder contains the appcfg.cmd command.

2) Under a DOS command prompt, go to the workspace folder of your project and launch the following command :
"D:\Dev\eclipse-jee-helios-SR1-win32\plugins\com.google.appengine.eclipse.sdkbundle.1.4.2_1.4.2.v201102111811\appengine-java-sdk-1.4.2\bin\appcfg" rollback war

After that, you can try to deploy the app again and it should work.

Links :
http://code.google.com/intl/fr/appengine/docs/java/tools/uploadinganapp.html
http://code.google.com/intl/fr/appengine/docs/java/gettingstarted/uploading.html

Categories: Google App Engine, GWT Tags:

[Tutorial] Create your first GWT project and deploy it to GAE

April 9th, 2011 No comments

Here is a first quick and simple tutorial on how to develop and deploy your very first GWT web application to Google App Engine.

Requirements :
Eclipse
Google Web Toolkit plugin for Eclipse
A Google App Engine account + GMAIL account

So here are the steps :
Read more…

Categories: Google App Engine, GWT, Tutorials Tags: