Thursday, December 22, 2011

HTML5 history support in mobile browsers

For those of you who don`t know theres a new HTML5 API out there for handling the browsers history. (eg. what happens when the user presses back, or reloads the page)

It provides the following functions:

  • change the current history entry (replaceState)
  • add a new history entry onto the stack (pushState)
  • receive an event if the stack has changed(user pressing forward or back)
  • Get the size of the history stack
  • go forward and backwards in history
Together this set of apis provides a nice way to handle the android back button inside a web application. You can actually mimic the behavior of a native app with the back button, as long as android supports the html5 history api.

I was very pleased to see support for this in android 2.2 and android 2.3, but was kind of worried to see that this was not working properly in android 3.x. But I wasn't too worried, because android 3.x was rushed to get out the door and never really had that much devices ( see: http://developer.android.com/resources/dashboard/platform-versions.html)

When I installed android 4.0 last week on my phone I was very surprised to see that mgwt used a fallback mechanism (introduced for the few android 3.x devices) to get the back button working. So I did some digging and was able to find out that that android 4.0 does not support html5 history api.


Why is HTML5 history support important?
If you want to use the back button properly with your android web app, you need to get an event when the user presses that back button. If the browser does not support the html5 history api you can still get an event by using a hashtag mechanism in the url (like GWT has done for quite a long time), but you will not be able to change the current entry on the history stack. So you will get inconsistencies when trying to mimic the behavior of the android activity stack.
The second thing is performance: It seems that the history pop event fires immediately, while the hashtag mechanism needs on my phone at least one second before the gwt app sees the action. This leeds to a serious sluggish feeling when using the back button. I haven't had the time to look into this maybe there is something that can be done about it.

But:
There is a discussion in the gwt contributer group ( https://mail.google.com/mail/#label/gwt-contrib/1345fe21e2ad68ed) that discusses if we can implement a history replace mechanism on top of the hash tag mechanism so there might be a way to get some decent behavior in web apps inside android 4. 

This leaves me wondering what google is doing with android and why it is so hard for them to have a matching browser to apples mobile safari. This is working properly on android 2.2 and 2.3, why is it not working in android 4?

Also there wasn't any issue on the android tracker regarding this. I will be doing some more research and post a bug report eventually, so that we can get this fixed some time in the future... 
Someone else already file a bug (see http://code.google.com/p/android/issues/detail?id=23979)

Also I will try to find a way to get the best possible current solution for mgwt web apps (note: with gwt-phonegap you can get a direct event if the user presses the back button).


Tuesday, December 13, 2011

mgwt 1.0.1 released

A month after the first non beta release, I am very happy to report the next release of mgwt: 1.0.1

This release contains some new features as well as bugfixes. A detailed description can be found here: http://code.google.com/p/mgwt/wiki/Changes

There also have been many improvements to the documentation. I encourage you to check them out here: http://code.google.com/p/mgwt/wiki/


As always the release is also available from central:
<dependency>
      <groupId>com.googlecode.mgwt</groupId>
      <artifactId>mgwt</artifactId>
      <version>1.0.1</version>
</dependency>

Friday, December 2, 2011

Animating in the browser

With this blog post I wanted to give a quick overview about how you can animate inside the browser and give some advice on best practices.


There are several ways to animate inside the browser:
  1. Continuously change screen from javascript
    • using setTimeout / setInterval
    • using requestAnimationFrame
  2. Using the layout engine
    • CSS3 Animations
    • CSS3 Transformations
Using the layout engine for your animations has several benefits. You declare your animations in a declarative fashion and the browser can find an efficient way to display that animation.




Let's take a look at an example. Let's say we want to move a div from position A to position B in a specific time. Something like this:






If we are doing this in Javascript we would be doing something like this: building a function, which moves the div a little and calling that function repeatedly until we reach the end position.
This is what the code would look like:


$(document).ready(function(){
    $("#button").click(function(){
       
        var time = 1000; // animation time in ms
        var start = new Date().getTime();
        var end = start + time;
        var left = 0; //start position
        
        window.setTimeout(animate, 10);
        
        function animate(){
            var now = new Date().getTime();
            left = (now - start) / 10; //update position
             $("#test").offset({top: 0, left: left});
            if(now < end)     
            {
                window.setTimeout(animate, 10);
            }else{
                $("#test").offset({top: 0, left: 100});
            }
        }
        
    });
});




Here is a small jsfiddle with a complete example.


The problem:
This can not be optimized by the browser / layout engine, because it does not know about the whole movement. It only knows about the small fraction of the movement.
Also we need the JavaScript VM running as well as the layout engine, which will consume a lot of CPU cycles. This might be okay for desktop, but it`s bad for mobile.
On mobile we are running on battery with slow CPUs, so we don`t want to do unnecessary things.


So for simple transitions of your UI why do them in JavaScript at all?


The solution:
If we specify the complete transition in a declarative way the browser could take care of optimizing it for us. This is what CSS3 Animations and CSS3 Transitions are about. Instead of updating the position in a "loop" we simply say move from here to there in some time. In CSS3 (for a webkit browser) this looks like this:


.move {
 -webkit-animation-name: moveAnimation; /*name of the animation */
 -webkit-animation-timing-function: ease-in-out; /* timing function */
 -webkit-animation-duration: 1000ms; /* duration for the animation */

}

@-webkit-keyframes moveAnimation {
    from { -webkit-transform: translateX(0); }
    to { -webkit-transform: translateX(100px); }
}

With the keyframes you can control any point in the transition and you can use even more than one css property. Many mobile browser can take something like this and just run it on their GPU, so we don't get any CPU what so ever. This produces very smooth and nice looking animations.


Now you have a basic idea how the two different approaches work. Lets quickly remind ourselves what the pros and cons are:




Animating in JavaScript
  • JavaScript VM needs to run
  • Can not be optimized
  • Good control over every detail
  • Inefficient
Animating with CSS3
  • Only Layout engine needs to run
  • Can be heavily optimized, executed with hardware support
  • Complex updates are hard to write


requestAnimationFrame vs. setTimeout
If you are animating with setTimeout or setInterval you should be considering using requestAnimationFrame. It has two main advantages: It runs synchronized with the display frame rate and it does not run if the webpage is not visible.

If you are using setTimeout for animating your animation loop is even running if the user is currently looking at another tab. This is why browser vendors added requestAnimationFrame so that your code would not be executed if it does not need to. Also you may be calculating things which will never be drawn on screen, because you don`t know when the browser will actually paint the DOM.

Paul Irish has written a nice post about requestAnimationFrame, I encourage you to read it if you want to know more.




Some advice
If you want smooth running animations consider using CSS3 Animations / CSS Transitions. They run much smoother than handwritten animations on many devices, but they can only be used if you are animating DOM Objects.

If you want to animate the content of a canvas element you need to do your updates in javascript using requestAnimationFrame. This is the way canvas is ment to be used and this is fine.

CSS3 Animations and CSS3 Transitions are mostly the same, but the syntax for transitions can be quite clunky if you want to transition over multiple elements.

Depending on your target platform you should be using different approaches. Webkit animations are very good supported with all iOS devices, but with android you should be using CSS3 transition. They work more reliably across android devices.

If you want to see some animations in action take a look at mgwt. 




















Wednesday, November 16, 2011

How to mavenize your GWT eclipse projects

Maven and gwt eclipse projects haven`t been playing nicely with each other for quite some time now. There are always some little gotchas that might get you. For me I found a way that works nicely and so I decided to share. This is based on Google Plugin for Eclipse 3.6 Version 2.4.2.relr36v201110112027 and maven 3.0.3.

Update 1:
Users running this on windows reported problems with the linked war file. Changing the path for the linked file using an eclipse variable solves this. I updated the post to reflect this.

Update 2:
As Thorsten pointed out running mvn war:exploded is much faster than running mvn war:war . Updated the post.

The first thing I like to have is one single point of configuration and not a plit up configuration in many different places. To me this is what the pom.xml is for. So I wanted to have a way to be able to set up everything from the pom and let maven write the files that I need in eclipse. (Like .project and .classpath)  First thing for me was to declare the gwt version as a property like this:
<properties>
   <gwtversion>2.4.0</gwtversion>
</properties>
Next up you simply declare gwt as a dependency:
<dependency>
  <groupId>com.google.gwt</groupId>
  <artifactId>gwt-user</artifactId>
  <version>${gwtversion}</version>
</dependency>
<dependency>
  <groupId>com.google.gwt</groupId>
  <artifactId>gwt-servlet</artifactId>
  <version>${gwtversion}</version>
</dependency>
<dependency>
  <groupId>javax.validation</groupId>
  <artifactId>validation-api</artifactId>
  <version>1.0.0.GA</version>
  </dependency>
<dependency>
   <groupId>javax.validation</groupId>
   <artifactId>validation-api</artifactId>
   <version>1.0.0.GA</version>
   <classifier>sources</classifier>
</dependency>
So far nothing fancy, but right now maven would not be able to compile your gwt sources to javascript. For that we are using the gwt-maven-plugin:
<plugin>
   <groupId>org.codehaus.mojo</groupId>
   <artifactId>gwt-maven-plugin</artifactId>
   <version>${gwtversion}</version>
   <executions>
      <execution>
         <goals>
            <goal>compile</goal>
            <goal>test</goal>
         </goals>
      </execution>
   </executions>
</plugin>
Note: If for some reason you want to use a different version of the gwt-maven-plugin (using a newer version of the plugin with gwt trunk), you can set this version manually. Because the gwt-maven-plugin takes care of adding gwt-dev to the classpath for compilation only, we avoid having nasty dependency conflicts. So up to know you can simply run mvn package on the console and you will get a nice artifat compiled with gwt, but there is no integration with eclipse so far. For that we are going to use the maven-eclipse-plugin with some nice tricks. First the whole plugin configuration:
<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-eclipse-plugin</artifactId>
   <version>2.8</version>

   <configuration>
      <downloadSources>true</downloadSources>
      <downloadJavadocs>true</downloadJavadocs>
      <buildOutputDirectory>war/WEB-INF/classes</buildOutputDirectory>
      <projectnatures>
         <projectnature>org.eclipse.jdt.core.javanature</projectnature
         <projectnature>com.google.gdt.eclipse.core.webAppNature</projectnature>
         <nature>com.google.gwt.eclipse.core.gwtNature</nature>
      </projectnatures>
     
      <buildcommands>
         <buildcommand>org.eclipse.jdt.core.javabuilder</buildcommand>
         <buildcommand>com.google.gdt.eclipse.core.webAppProjectValidator</buildcommand>
         <buildcommand>com.google.appengine.eclipse.core.projectValidator</buildcommand>
         <buildcommand>com.google.gwt.eclipse.core.gwtProjectValidator</buildcommand>
      </buildcommands>

      <classpathContainers>
         <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
         <classpathContainer>com.google.gwt.eclipse.core.GWT_CONTAINER</classpathContainer>
      </classpathContainers>
     
      <excludes>
         <exclude>com.google.gwt:gwt-servlet</exclude>
         <exclude>com.google.gwt:gwt-user</exclude>
         <exclude>com.google.gwt:gwt-dev</exclude>
         <exclude>javax.validation:validation-api</exclude>
      </excludes>

      <linkedResources>
         <linkedResource>
            <name>war
            <type>2
            <location>PROJECT_LOC/target/${project.artifactId}-${project.version}</location>
  </linkedResource>
      </linkedResources>

   </configuration>
</plugin>


Lets discuss the different parts in detail:
<linkedResources>
   <linkedResource>
   <name>war
   <type>2
   <location>PROJECT_LOC/target/${project.artifactId}-${project.version}</location>
   </linkedResource>
</linkedResources>
This adds a linked directory to your eclipse project which actually points to the compile directory of maven. So your build from eclipse just use the same output directory. This is quite useful because the google eclipse plugin won't complain about the compile target of the project, but still will deploy to a temporary directory (and not src/main/webapp)

With this part you tell eclipse to complile into the linked directory:
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<buildOutputDirectory>war/WEB-INF/classes</buildOutputDirectory>


We also have to set the right project natures so that our project is regonzied as java, gwt and a wepp app project:
<projectnatures>
   <projectnature>org.eclipse.jdt.core.javanature</projectnature
   <projectnature>com.google.gdt.eclipse.core.webAppNature</projectnature>
   <nature>com.google.gwt.eclipse.core.gwtNature</nature>
</projectnatures>


And we have to configure the right builders for our project:
<buildcommands>
   <buildcommand>org.eclipse.jdt.core.javabuilder</buildcommand>
   <buildcommand>com.google.gdt.eclipse.core.webAppProjectValidator</buildcommand>
   <buildcommand>com.google.appengine.eclipse.core.projectValidator</buildcommand>
   <buildcommand>com.google.gwt.eclipse.core.gwtProjectValidator</buildcommand>
</buildcommands>


Also we want to have the GWT SDK and the Java SDK on our buildpath:
<classpathContainers>
   <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
   <classpathContainer>com.google.gwt.eclipse.core.GWT_CONTAINER</classpathContainer>
</classpathContainers>


And we have to make sure that gwt maven dependencies are not on the classpath, because the google eclipse plugin needs the local SDK jars to work properly. So for eclipse project we exclude them (google eclipse plugin will provide them).
<excludes>
   <exclude>com.google.gwt:gwt-servlet</exclude>
   <exclude>com.google.gwt:gwt-user</exclude>
   <exclude>com.google.gwt:gwt-dev</exclude>
   <exclude>javax.validation:validation-api</exclude>
</excludes>


If you set up your project to include this in your pom, you can now simply to:

mvn eclipse:eclipse 
mvn war:exploded 

 and import the project into eclipse:

File -> Import -> General -> Existing Projects into Workspace


The one thing I was not able to figure out was how to tell the google eclipse plugin that gwt-servlet and gwt-user are already inside war/WEB-INF/lib, so you still get a warning about that. Something like : 

"The GWT SDK JAR gwt-servlet.jar is missing in the WEB-INF/lib directory"

But you can simply use the quick fix:

> Synchronize /WEB-INF/lib with SDK libaries. 


The google eclipse plugin will copy the gwt-servlet.jar into your WEB-INF/lib folder and you are good to go. I will try to talk about this last issue with some developers from google at the google developer weekend to get this working all the way. For me this is the best way right now to work with maven and gwt in eclipse.


If you did something to your project which needs to rewrite the eclipse project files you can do:


mvn eclipse:clean
mvn eclipse:eclipse


If you are making changes to src/main/webapp that need to be reflected in your war directory, simply run:


mvn war:exploded


For those interested here is a complete pom example from the mgwt showcase:
<?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">



 <modelVersion>4.0.0</modelVersion>
 <groupId>com.googlecode.mgwt</groupId>
 <artifactId>mgwt-showcase</artifactId>
 <version>1.0.0-SNAPSHOT</version>
 <packaging>war</packaging>
 <name>Mobile GWT Showcase</name>

 <properties>
  <gwtversion>2.4.0</gwtversion>
 </properties>

 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
     <source>1.6</source>
     <target>1.6</target>
    </configuration>
   </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>
      </goals>
     </execution>
    </executions>
   </plugin>

   

   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-eclipse-plugin</artifactId>
    <version>2.8</version>

    <configuration>
     <downloadSources>true</downloadSources>
     <downloadJavadocs>false</downloadJavadocs>
     <buildOutputDirectory>war/WEB-INF/classes</buildOutputDirectory>
     <projectnatures>
      <projectnature>org.eclipse.jdt.core.javanature</projectnature>
      <projectnature>com.google.gdt.eclipse.core.webAppNature</projectnature>

      <nature>com.google.gwt.eclipse.core.gwtNature</nature>
     </projectnatures>
     <buildcommands>
      <buildcommand>org.eclipse.jdt.core.javabuilder</buildcommand>
      <buildcommand>com.google.gdt.eclipse.core.webAppProjectValidator</buildcommand>

      <buildcommand>com.google.appengine.eclipse.core.projectValidator</buildcommand>
      <buildcommand>com.google.gwt.eclipse.core.gwtProjectValidator</buildcommand>
     </buildcommands>
     <classpathContainers>
      <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>

      <classpathContainer>com.google.gwt.eclipse.core.GWT_CONTAINER</classpathContainer>
     </classpathContainers>
     <excludes>
      <exclude>com.google.gwt:gwt-servlet</exclude>
      <exclude>com.google.gwt:gwt-user</exclude>
      <exclude>com.google.gwt:gwt-dev</exclude>
      <exclude>javax.validation:validation-api</exclude>
     </excludes>
     <linkedResources>
      <linkedResource>
       <name>war</name>
       <type>2</type>
       <location>PROJECT_LOC/target/${project.artifactId}-${project.version}</location>
      </linkedResource>
     </linkedResources>

    </configuration>
   </plugin>
   <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
     <execution>
      <id>assemble</id>
      <phase>package</phase>
      <goals>
       <goal>single</goal>
      </goals>
     </execution>
    </executions>
    <configuration>
     <descriptors>
      <descriptor>src/main/assembly/clientcode.xml</descriptor>
     </descriptors>
    </configuration>
   </plugin>
  </plugins>
  <resources>
   <resource>
    <directory>src/main/java</directory>
    <includes>
     <include>**/client/**</include>
     <include>**/*.gwt.xml</include>
    </includes>
   </resource>
  </resources>
 </build>

 <dependencies>
  <dependency>
   <groupId>com.googlecode.mgwt</groupId>
   <artifactId>mgwt</artifactId>
   <version>1.0.1-SNAPSHOT</version>

  </dependency>

  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.7</version>
   <type>jar</type>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>com.google.gwt</groupId>
   <artifactId>gwt-user</artifactId>
   <version>${gwtversion}</version>
  </dependency>
  <dependency>
   <groupId>com.google.gwt</groupId>
   <artifactId>gwt-servlet</artifactId>
   <version>${gwtversion}</version>
  </dependency>
  <dependency>
   <groupId>javax.validation</groupId>
   <artifactId>validation-api</artifactId>
   <version>1.0.0.GA</version>
  </dependency>
  <dependency>
   <groupId>javax.validation</groupId>
   <artifactId>validation-api</artifactId>
   <version>1.0.0.GA</version>
   <classifier>sources</classifier>
  </dependency>
 </dependencies>



</project>

Monday, November 14, 2011

mgwt 1.0 released

After more than 1,5 years I am very happy to announce the first non-beta release of mgwt. During the last three months I was able to put a tremendous amount of time into this project. For a quick overview checkout the Showcase with a webkit browser (e.g. Chrome, Safari, ...) or your phone / tablet.
This release supports:
  • iPhone
  • iPhone Retina Displays
  • iPad
  • Android Phones
  • Android Tablets
  • blackberry phones
With this release you get:
  • Great looking fast animations integrated with GWT MVP
  • Nice set of good looking widgets
  • Performance because we leverage CSS3 as much as possible (no images, animations in css and many more details)
  • Great looking styles for each platform
  • UiBinder support for all widgets
  • Editor support for all widgets
  • Deferred Binding for all major diffs
We love working with GWT and this is why mgwt does not try to replace GWT. Instead it uses best practices you already know from GWT and extends it where needed. If you want to know why we decided to go with GWT in the first place to do mobile development, this wiki page sums it up nicely. We know that the current documentation needs improvement and we will start to improve it very soon. To get started with developing great mobile apps checkout Getting started wiki page and also take a look at m-gwt.com for a brief overview. This is just the start and we are very excited about the future of mgwt. If you have any questions or suggestions as always don't hesitate to ask. mgwt is available from central:
<dependency>
      <groupId>com.googlecode.mgwt</groupId>
      <artifactId>mgwt</artifactId>
      <version>1.0.0</version>
</dependency>

Saturday, November 12, 2011

GWT-Phonegap 1.2 released

In preparation for the google developer day I was very anxious to support the latest version of phonegap.

To get a good overview of the current state of gwt-phonegap you can take a look at the features page of the wiki. As always if you have any feedback or problems feel free to use the usergroup.

This release is also available from maven central:
<dependency>
      <groupId>com.googlecode.gwtphonegap</groupId>
      <artifactId>gwtphonegap</artifactId>
      <version>1.2.0.0</version>
</dependency>

Wednesday, October 12, 2011

gwt-phonegap in maven central repository

Using gwt-phonegap has become much easier since the project is now available from the maven central repository. You can use your favorite build tool to add the dependency. It is deployed with the groupId: com.googlecode.gwtphonegap and the artifactId: gwt-phonegap and version 1.0.0.0 For maven this would look like:
<dependency>
      <groupId>com.googlecode.gwtphonegap</groupId>
      <artifactId>gwtphonegap</artifactId>
      <version>1.0.0.0</version>
</dependency>
I hope that saves you a lot of local deployment time when using gwtphonegap. In the next couple of weeks I will also start an archetype for a standard gwtphonegap project, so getting stated will be much easier.

Monday, October 10, 2011

GWT-Phonegap version 1.0 released

Today I was finally able to release gwt-phonegap as 1.0. There has been a tremendous amount of work put into this and I want to thank all the people that contributed in any way.

GWT-Phonegap now supports the full phonegap API and provides a mocked functionality in gwt dev mode. In the next days I will concentrate on improving the documentation, so that getting to work with gwt-phonegap will become much more fun.

To see the full supported features you can checkout the feature tab.

In the next couple of weeks, I will also make the first 1.0 release for mgwt, so that the whole toolchain for creating great mobile apps with gwt will be in a supported released state.

As always if you have any feedback or problems feel free to use the usergroup.

For those who are wondering why I renamed all the packages to com.googlecode.gwtphonegap: This needed to be done to comply with the rules for maven central. I will try to get the project into maven central very soon, so that including it into your build environment will be much easier.

Wednesday, September 28, 2011

GWT-Phonegap nearing 1.0

In the last couple of weeks I was able to invest a substantial amount of time into gwt-phonegap and mgwt. The work on gwt-phonegap is almost complete and it supports all of the phonegap api.

If you are running in dev mode, gwt-phonegap will emulate the phonegap apis, so that you will be able to develop your phonegap app in your safari / chrome on your desktop machine and later compile it down to javascript. This is done with gwt deferred binding so there are no runtime costs at all.

Also the documentation has had some major improvements, so that it will be much easier to get started with gwt-phonegap.

One major thing that happened was to change the package structure from de.kurka to com.googlecode.gwtphonegap to meet the requirements for artifacts to be uploaded the the central maven repository.

I will be releasing the first beta of gwt-phonegap 1.0.0.0 very soon and if all goes well, we are going to have an release in the central repo very soon.

In the next couple of weeks I will be focusing to get mgwt to 1.0 as well

Tuesday, May 3, 2011

gwt-dispatch and Custom Header or Basic Authentification

gwt-dispatch is an open source implementation of the command pattern, which is very well suited for use with GWT RPC.

In order to set Custom Headers in GWT you need to get the RequestBuilder instance which will perform the request under the covers for you.

There are two ways to do this:
  1. Let your Async Interface return RequestBuilder instead of void
  2. You can provide an instance of RPCRequestBuilder to your service, which will construct the RequestBuilderInstance

Using option one has the disadvantages that you have to send your request manually, thus changing the DispachAsync interface would break a lot of current applications (and introduce a lot of redundant code). So I was looking for another options.


You can downcast your service to ServiceDefTarget and set an instance of RPCRequestBuilder like this:

service = GWT.create(Dispatch.class);
((ServiceDefTarget) service).setRpcRequestBuilder(this.authenticatingRequestBuilder);


With and RPCRequestBuilder looking like this:

public class ACustomRequestBuilder extends RpcRequestBuilder {

@Override
protected RequestBuilder doCreate(String serviceEntryPoint) {
RequestBuilder requestBuilder = super.doCreate(serviceEntryPoint);
requestBuilder.setHeader("your header", "your value");
return requestBuilder;
}
}




Now you can easily control all aspects of your request.

Thanks to Robert Muntenau this is now also in the gwt-dispatch docs: http://code.google.com/docreader/#p=gwt-dispatch&s=gwt-dispatch&t=RequestBuilder

Saturday, April 16, 2011

Testcoverage in general and with GWT MVP

I have always been criticized about my view on minimal test coverage of code.

I always advocated that any test coverage below 100% may lead to the following:
Only the easy to cover parts of the software get tested. The hard parts will be left out. (I already have a sufficient part tested, why spend more time?). The really tricky edge cases will be left out sometimes entirely.

To make myself clear: I am not taking about 100% input coverage. Every line of code that will run in production should behave as expected (or intended by the developer). To make sure you should run through this code at least one time to state your intention. This will not in any way prove that your product doesn't have any bugs. It will just reduce the number of bugs.

Sometimes I heard the argument that this is fine for backend code where it's easy to mock out dependencies, but does not translate to UI programming. That's just not true: if you take a look at GWT MVP you get a very good idea how to isolate your presentation logic from the UI fields and you can test most of your code in a simple JUnit Test Case.

Me personally I like EMMA a lot. It's an open-source toolkit for measuring and reporting Java code coverage, which has a nice integration in eclipse and maven as well. Basically in eclipse it marks a line in your code green, yellow or red. Red meaning that this part of the code was never executed during your tests. Green meaning this part of the code was executed. Yellow meaning that only part of your code was executed. It also sums up test coverage for packages.

Using EMMA you can quickly discover the dirty spots in your project and improve their test coverage. I even trigger built failures if the test coverage drops from a previous built, so that you can only check in tested code.

But if you think about a normal GWT MVP project you will end up with a few untested places like your Entrypoint with all the initialization, and those view implementations. It's not possible to test them in simple JUnit Test and so it's not possible to test them very quickly at all. Quick feedback to your commits is very important, so what can we do about those. First we exclude them from EMMA so that we only measure the testable code. Second thing is that most of the code is simple UI plumbing stuff. So we can get a decent coverage (which is sufficient) in our UI Test with selenium for instance.

Monday, March 21, 2011

gwt-phonegap 0.8

The next release of gwt-phonegap 0.8 is ready to be downloaed.

The Contacts API is now part of the project and two plugins Childbrowser and Badge.

The main improvement is that gwt-phonegap now runs inside your desktop browser (with an emulated implementation). By using GWT.create to create the instance of the new phonegap interface we can easily detect the environment and load the appropriate gwt-phonegap implemenation. This makes it much easier to develop your phonegap app in the browser.

The new version is now the featured download on the project page.

Monday, March 14, 2011

gwt phonegap 0.7 realeased

Today I found the time to update gwt-phonegap to the latest phonegap version 0.9.4 and gwt 2.2.

The new version can be downloaded here

Note:
If you start using phonegap 0.9.4 on iOS there is an issue with the Phonegap Network interface (isReachable). I`m going to update the issue. A valid workaround is described here.

Tuesday, February 22, 2011

mgwt 0.5a

About one and a half years ago I started developing applications for the iPhone using GWT and phonegap. At the moment GWT is not quite a fit for mobile development so I had to adjust the tool and do some ground work.

After using mgwt for my personal mobile developement I had some great responses from colleagues telling me to open source my work. It took me quite a while to start sharing because I am one of those persons who like to show of with perfect code, but at some point I realized that I should be sharing as soon as possible to get some feedback.

So the first wave of open sourcing consists of:
  1. the GWT Events (touchstart, touchmove, touchend, touchcancel, animationend, transistionend) integrated with the GWT event System
  2. Anitmations integrated with GWT MVP
  3. Styling for iPhone
  4. Lots and lots of widgets

I also have a theme for iPads and Android which I would like to share at some later point (they are just not ready yet). I am very excited about mgwt and hope to find some people that are exited as well about developing mobile apps with gwt.

Any feedback is very much welcome!

So if you like to see what mgwt is like check out www.m-gwt.com

Saturday, January 1, 2011

GWT RPC with Phonegap

Update: This is no longer necessary. Take a look at a newer post!


I have been asked a couple of times now how to use gwt rpc with phonegap applications. Right now this does not work out of the box for a simple reason:

For security reasons phonegap starts your application locally (not http:// but file://pathToYourApp/www/index.html). GWT on the other hand assumes that it will find the services by appending your annotated servlet path to the base url. So GWT phonegap applications out of the box try to find their services locally.

In order to fix this you have to do a couple of things (which will be included in the next version of gwt-phonegap)

You have to set the url of your servlet in the proxy service interface like so:

DispatchServiceAsync realService = GWT.create(DispatchService.class);
ServiceDefTarget service = (ServiceDefTarget) realService;
service.setServiceEntryPoint("http://www.daniel-kurka.de/yourservice");

Normally I include a switch for production and dev time.


The other thing that is not working out of the box is the RemoteServiceServlet. I looks for the gwt.rpc files at the url that the client tells it (which would be file:// something). So serialization of some object may fail because its working in gwt 1.3 mode.

To fix this you can just look locally for those files by overriding doGetSerializationPolicy like this:


@Singleton
public class PhoneGapDispatchServiceServlet extends RemoteServiceServlet implements DispatchService {

 private static final long serialVersionUID = 9114953736786309471L;
 private final Dispatch dispatch;

 private Logger logger = Logger.getLogger(getClass().getName());

 @Inject
 public PhoneGapDispatchServiceServlet(Dispatch dispatch) {
  this.dispatch = dispatch;
 }

 public Result execute(Action action) throws ActionException {
  try {
   return dispatch.execute(action);
  } catch (RuntimeException e) {
   logger.log(Level.SEVERE, "Exception while executing " + action.getClass().getName(), e);
   throw new ActionException("runtime exception occured while dispatching action");
  }
 }

 private String getBaseUrl(HttpServletRequest request) {
  if (request.getServerPort() == 80 || request.getServerPort() == 443)
   return request.getScheme() + "://" + "127.0.0.1" + request.getContextPath() + "/iphone/";
  else
   return request.getScheme() + "://" + "127.0.0.1" + ":" + request.getServerPort() + request.getContextPath() + "/iphone/";

 }

 @Override
 protected SerializationPolicy doGetSerializationPolicy(HttpServletRequest request, String moduleBaseURL, String strongName) {

  String baseUrl = getBaseUrl(request);
  logger.info("localUrl: " + baseUrl);

  return super.doGetSerializationPolicy(request, baseUrl, strongName);
 }

}


This is all you have to do to get GWT RPC working with phonegap apps.