GWT Offline application

How to use the linker file in GWT to automatically update the cache manifest file to enable offline capabilities in GWT web app.

HTML5 Offline application

HTML5 offers a way to use the web application in the offline mode. When application is loaded for the first time, the entire site (css files, javascript files, images etc) can be cached on the browser so that next subsequent  visits can be fulfilled from the cache when the internet is disconnected. 

Enabling a site that has offline capabilities is simple. Just adding a single manifest file is enough. The following offline.appcache fines a list of files that should be cached for the given site. 

Cache maiftest file

		CACHE MANIFEST
      
# This is a comment

CACHE:
/myapp.css
/myapp.html

NETWORK:
/index.html  

Problem in GWT?

There is a problem in GWT application to activate offline features for the applications. The problem is GWT compiler automatically generates lots of css and javascript files that are essential to run the application. So every time the GWT complies there will be different set of files with different files names. 

To make the application work on offline mode, we must make sure that the cache manifest file is up-to date after each GWT compilation. 

Don't worry there is a way to create custom linker class in GWT that does the job (updating the cache manifest file on the fly every time GWT completes compiling the source).

 

Linker class

		import com.google.gwt.core.ext.LinkerContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.AbstractLinker;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.EmittedArtifact;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.LinkerOrder.Order;

@LinkerOrder(Order.POST) 
public class OfflineLinker extends AbstractLinker {
	@Override
	public String getDescription() {
		return "Offline Linker";
	}
	
	 @Override
	  public ArtifactSet link(TreeLogger logger, LinkerContext context,ArtifactSet artifacts) throws UnableToCompleteException {
	    ArtifactSet artifactset = new ArtifactSet(artifacts);

	    StringBuilder builder= new StringBuilder("CACHE MANIFEST\n");
	    builder.append("# Cache Version 10\n");
	    builder.append("CACHE:\n");

	    builder.append("/myapp.css\n");
	    builder.append("/myapp.html\n");    
	    for(EmittedArtifact emitted: artifacts.find(EmittedArtifact.class))
	    {
	    	if(emitted.isPrivate())
	    	{
	    		continue;
	    	}
	    	if(emitted.getPartialPath().endsWith(".symbolMap"))continue;
	    	if(emitted.getPartialPath().endsWith(".txt"))continue;
	    	builder.append("/myapp/" + emitted.getPartialPath()).append("\n");
	    }
	    builder.append("/myapp/hosted.html\n");
	    builder.append("/myapp/myapp.nocache.js\n");
	    builder.append("NETWORK:\n");
	    builder.append("*\n");
	    EmittedArtifact manifest= emitString(logger, builder.toString(), "offline.appcache");
	    artifactset.add(manifest);
	    return artifactset;
	  }
} 

How to use linker?

You can specify in the module definition file which linker to user? Just add the following lines of code in the your.gwt.html file. 

<define-linker class="com.oh5.OfflineLinker" name="offline" />

<add-linker name="offline" />

Complete myapp.gwt.html

		<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='myapp'>
	<!-- Inherit the core Web Toolkit stuff. -->
	<inherits name='com.google.gwt.user.User' />
	<inherits name="com.google.gwt.json.JSON" />
	<!-- Inherit the default GWT style sheet. You can change -->
	<!-- the theme of your GWT application by uncommenting -->
	<!-- any one of the following lines. -->
	<inherits name='com.google.gwt.user.theme.clean.Clean' />
	
	<!-- Other module inherits -->

	<!-- Specify the app entry point class. -->
	<entry-point class='com.oh5.client.myapp' />

	<!-- Specify the paths for translatable code -->
	<source path='client' />
	<source path='shared' />
	<define-linker class="com.oh5.OfflineLinker" name="offline" />
	<add-linker name="offline" />
</module> 

After the GWT complilation complets, the manifest file will be automatically update with the new javsascript and css files. 

Here is the complete file after the GWT compilation. 

		CACHE MANIFEST
      
# This is a comment

CACHE:
/myapp.css
/myapp.html

/myapp/0A9476898799A150D840F0B1C3672921.cache.png
/myapp/27929D4B3D526C5EDCAE430864B78EE0.cache.html
/myapp/396F806CD63ABD414BFBB9D57429F05B.cache.png
/myapp/492E56E77AC41ACAAC69482D63743D10.cache.html
/myapp/85938CB73A765675E68F65D5D0C067D6.cache.html
/myapp/ADD45C0D50B41BA6DC25099C1EF6A974.cache.html
/myapp/B10EEA753EEAD5C0D726312E59A0B29E.cache.html
/myapp/BE2EB462D8BAA6C12A017DD3B5B16A65.gwt.rpc
/myapp/clear.cache.gif
/myapp/D9E580486441ABFC13F41104A7EAC514.cache.html
/myapp/DF7764EEC1903CD03C9545B354D8D8E4.cache.png
/myapp/E44767377485D18D6B6864F65BA8EF73.cache.png
/myapp/EDC7827FEEA59EE44AD790B1C6430C45.cache.png
/myapp/hosted.html
/myapp/htmllocalstoragep.nocache.js


NETWORK:
/index.html 

Like us

See also

GWT Offline application

How to use the linker file in GWT to automatically update the cache manifest file to enable offline capabilities in GWT web app.

GWT and HTML5 Support

Here we gonna talk about how do we gonna use HTML 5 in GWT applications. Also with some practical examples.