I took an example Touchkit application and started trying things with it, writing an app for my daughter’s wedding. It uses NavigationViews with buttons to move to other NavigationViews, essentially.
I’ve got it running on Tomcat, both locally and on a friend’s server. But on the server, with a lower bandwidth, the app takes 20-60 seconds to load the first page. I looked at HTTP traffic (using Fiddler) on my own server, and there’s 2-3 Megabytes of information that gets transferred to the phone before it displays the first page.
I am trying to GZIP the download, but even if that cuts the time in half it’s really too long. So I’ve been trying to figure out how to “Optimize the widgetset”. I understand the concept – the JavaScript that is output by the compiler does not by default know which widgets are used in the program, so there is (evidently) a way to list them and limit the widgetset compilation to only those widgets.
But I haven’t found an explanation of how this works, only an example. So I looked at the two files I understand to be relevant in the Parking App example – ParkingWidgetset.gwt.xml and WidgetLoaderFactory. I ended up with the following two files, first the gwt.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">
<module>
<!--
This file is automatically updated based on new dependencies by the
goal "vaadin:update-widgetset".
-->
<!-- Inherit DefaultWidgetSet -->
<inherits name="com.vaadin.DefaultWidgetSet" />
<inherits name="com.vaadin.addon.touchkit.gwt.TouchKitWidgetSet" />
<generate-with class="rc.wedding.ui.WidgetLoaderFactory">
<when-type-assignable class="com.vaadin.client.metadata.ConnectorBundleLoader" />
</generate-with>
</module>
Then the WidgetLoaderFactory:
package rc.wedding.ui;
import java.util.ArrayList;
import java.util.Collection;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.vaadin.addon.touchkit.gwt.TouchKitBundleLoaderFactory;
import com.vaadin.addon.touchkit.gwt.client.vcom.DatePickerConnector;
import com.vaadin.addon.touchkit.gwt.client.vcom.EmailFieldConnector;
import com.vaadin.addon.touchkit.gwt.client.vcom.GeolocatorConnector;
import com.vaadin.addon.touchkit.gwt.client.vcom.TabBarConnector;
import com.vaadin.addon.touchkit.gwt.client.vcom.VerticalComponentGroupConnector;
import com.vaadin.addon.touchkit.gwt.client.vcom.navigation.NavigationBarConnector;
import com.vaadin.addon.touchkit.gwt.client.vcom.navigation.NavigationButtonConnector;
import com.vaadin.addon.touchkit.gwt.client.vcom.navigation.NavigationManagerConnector;
import com.vaadin.addon.touchkit.gwt.client.vcom.navigation.NavigationViewConnector;
import com.vaadin.addon.touchkit.gwt.client.vcom.popover.PopoverConnector;
import com.vaadin.client.extensions.ResponsiveConnector;
import com.vaadin.client.extensions.javascriptmanager.JavaScriptManagerConnector;
import com.vaadin.client.ui.button.ButtonConnector;
import com.vaadin.client.ui.csslayout.CssLayoutConnector;
import com.vaadin.client.ui.form.FormConnector;
import com.vaadin.client.ui.formlayout.FormLayoutConnector;
import com.vaadin.client.ui.image.ImageConnector;
import com.vaadin.client.ui.label.LabelConnector;
import com.vaadin.client.ui.link.LinkConnector;
import com.vaadin.client.ui.nativeselect.NativeSelectConnector;
import com.vaadin.client.ui.optiongroup.OptionGroupConnector;
import com.vaadin.client.ui.table.TableConnector;
import com.vaadin.client.ui.textfield.TextFieldConnector;
import com.vaadin.client.ui.ui.UIConnector;
import com.vaadin.client.ui.upload.UploadConnector;
import com.vaadin.client.ui.window.WindowConnector;
import com.vaadin.shared.ui.Connect.LoadStyle;
public class WidgetLoaderFactory extends TouchKitBundleLoaderFactory
{
private final ArrayList<String> usedConnectors = new ArrayList<>();
public WidgetLoaderFactory()
{
addClass(ButtonConnector.class);
addClass(CssLayoutConnector.class);
addClass(DatePickerConnector.class);
addClass(EmailFieldConnector.class);
addClass(ImageConnector.class);
addClass(FormConnector.class);
addClass(FormLayoutConnector.class);
addClass(GeolocatorConnector.class);
addClass(LabelConnector.class);
addClass(LinkConnector.class);
addClass(NativeSelectConnector.class);
addClass(NavigationBarConnector.class);
addClass(NavigationButtonConnector.class);
addClass(NavigationManagerConnector.class);
addClass(NavigationViewConnector.class);
addClass(OptionGroupConnector.class);
addClass(PopoverConnector.class);
addClass(TabBarConnector.class);
addClass(TableConnector.class);
addClass(TextFieldConnector.class);
addClass(UIConnector.class);
addClass(UploadConnector.class);
addClass(VerticalComponentGroupConnector.class);
addClass(WindowConnector.class);
addClass(ResponsiveConnector.class);
addClass(JavaScriptManagerConnector.class);
}
private void addClass(Class<?> c) { usedConnectors.add(c.getName()); }
@Override
protected Collection<JClassType> getConnectorsForWidgetset(TreeLogger logger, TypeOracle typeOracle)
throws UnableToCompleteException
{
Collection<JClassType> connectorsForWidgetset
= super.getConnectorsForWidgetset(logger, typeOracle);
ArrayList<JClassType> arrayList = new ArrayList<>();
for (JClassType jClassType : connectorsForWidgetset)
{
String qualifiedSourceName = jClassType.getQualifiedSourceName();
if (usedConnectors.contains(qualifiedSourceName))
{
arrayList.add(jClassType);
}
}
return arrayList;
}
@Override protected LoadStyle getLoadStyle(JClassType connectorType)
{
return LoadStyle.EAGER;
}
}
And let me just say a word about compiling a Touchkit application – once you’ve messed with anything connected to the Widgetset (and I have not yet figured out everything that does), you are in for a treat. Some combination of the following will work, in some order, lots of the time:
- stop the server
- remove the app from the server
- clean the server
- clean the work directory of the server
- maven clean
- maven install
- maven compile
- add the app to the server
- start the server
I can usually count on doing most of these at least twice before the app will start again.
However, with the above two files in the project, the app doesn’t start – I get the “You seem to be using a desktop application” when I’m on my PC, but the page afterwards is just blank.
I don’t know where any log messages would be, or any other way to figure out what’s wrong. Can someone tell me if I’m missing something?
I think I have connectors for all my components, but if I’m missing one I don’t know how to find out. There was a suggestion in one of the articles to use a debugger on a class that had a list of all the components that had been used so far, but I couldn’t find the class in eclipse, either source or class.