26 Apr 2012, 11:04am
gwt:

leave a comment




  • Improving Canvas Performance

    1. Time­out instead of Scheduler

    Sur­pris­ingly, using com.google.gwt.user.client.Timer seems much faster then rely­ing on com.google.gwt.core.client.Scheduler. I did not yet eval­u­ate the dif­fer­ences in detail but the lower CPU work­load speaks for itself.

    2. Ani­ma­tion­Sched­uler

    I am not really sure if this helps a lot, but you will find a lot of online doc­u­men­ta­tion explain­ing that you should use this:
    com.google.gwt.animation.client.AnimationScheduler.get(). requestAnimationFrame(callback, element);. The ele­ment para­me­ter is optional but said to improve per­for­mance as the browser can decide when to ren­der opti­mally.
    So when­ever your timer kicks in, and you are ready to ren­der the results, use the Ani­ma­tion­Sched­uler instead of call­ing your ren­der­ing rou­tines right away. It will only take very few mil­lisec­onds (depend­ing on the users screen frame rate—which is 60 Hz or more usu­ally) for the call­back to return to your code.

    3. Caching

    This parts requires much more effort and depends on your soft­ware archi­tec­ture and require­ments. The basic idea is not to redraw things that did not change. To do so we can draw each item on a hid­den can­vas once and then reuse this ren­der­ing dur­ing every draw­ing cycle.
    As the process is a bit more com­pli­cated, I will ded­i­cate it a sep­a­rate post—comming soon!

    4. Save on effects

    Yes, effects is what the can­vas is all about, but some­thing like a shadow can cost quite some CPU power. So if you run into prob­lems check if some of the effects can be achieved cheaper or even be removed.

    26 Apr 2012, 9:58am
    gwt java:

    leave a comment




  • Multiple Projects and GWT

    When work­ing on sev­eral large scale projects (in Eclipse), it’s con­ve­nient and of course more effi­cient to share and reuse code via com­mon libraries. While those are in an early stage they need to be changed a lot and there­fore it’s handy to link projects in instead of cre­at­ing new jars each time the library has been updated.
    Unfor­tu­nately, this stan­dard approach for Java devel­op­ment in Eclipse does not work that straight for­ward as with plain old Java projects, it requires three steps in total:

    1. Link the library project to all rel­e­vant projects (“Project Pref­er­ences” -> “Java Build Path” -> “Projects” -> “Add…”)
    2. Then, add the client-side code of the library (by adding it as a mod­ule.) There­fore, edit the gwt.xml of your appli­ca­tion and add for exam­ple <inherits name="net.svenbuschbeck.gwt.lib.SuperLib "/> where Super­Lib is the file name of the gwt.xml file in you library project and before that is the pack­age it lies in.
    3. Add the code to the project by link­ing a source folder. Unfor­tu­nately, this is required if you do not want to write an Ant script to com­pile your appli­ca­tion. (If you pre­fer Ant check this out) I don’t like the idea of using such a script because if you for­get to run it each time you make changes, you will end up in confusion—let’s go for the con­ve­nient, auto­matic way then.
      1. Add a folder to your appli­ca­tion project; open the “advanced” sec­tion in the folder cre­ation dia­log, select “Link to alter­nate loca­tion” and pick the source folder (usu­ally “src”) of your library project. (Hint: if you work within a team using a ver­sion­ing sys­tem, you can cre­ate a vari­able for that folder and use this instead. This way, each of your col­leagues can put the library project in a dif­fer­ent folder and accom­mo­date for that by adjust­ing the vari­able :) )
      2. Right click the folder, “Build Path” -> “Use as Source Folder”. Done.

    Sur­pris­ingly, the GWT plu­gin for Eclipse does not honor the project link­ing, thus all the ref­er­ences need to be made explicit or you will end up with lots of the fol­low­ing: ClassNotFoundException.

    31 Jan 2012, 10:53am
    gwt java javascript:

    leave a comment




  • An invalid or illegal string was specified” Exception in GWT

    While work­ing with can­vas (draw­ing stuff on it) in GWT, sud­denly and in a seem­ingly unpre­dictable man­ner I got fol­low­ing error mes­sage now and then from within the GWT frame­work code:

    com.google.gwt.core.client.JavaScriptException: (NS_ERROR_DOM_SYNTAX_ERR): An invalid or illegal string was specified;

    Again, GWT tricked me into think­ing I am writ­ing Java code and made me for­get about that it is going to be com­piled into Javascript. And because of the lat­ter, a divi­sion by zero does not throw an Devi­sion­ByZe­roEx­cep­tion, no, it returns NaN even for native data types (there is no dif­fer­en­ti­a­tion between dou­ble and Dou­ble in Javascript — there is only the object-version of dou­ble, which can be of value Double.NaN).

    But also GWT was not pre­pared to han­dle Double.NaN. When call­ing canvas.getContext().drawImage(image,x,y) and one of x and y or both were Double.NaN I got the error mes­sage shown above. If you got the same… you know what to do now: check all devi­sions in your code for poten­tial devi­sions by zero!!

    18 Jan 2012, 10:50am
    gwt java:

    leave a comment




  • Sorting Lists in GWT

    Quick one:
    Lists.sort(list, comparator) is not imple­mented in the GAE JVM.
    But, as a replacement/alternative, Collections.sort(list, comparator) is.

    28 Feb 2011, 11:10pm
    gwt java:

    leave a comment




  • How to Execute Code When the GWT Application Is Going Down

    My goal was to store the UI state of my appli­ca­tion just before it gets ter­mi­nated to be able to restore it next time the way the user left it the other day.

    I tried to add an addAttachHandler to the RootPanel to get informed about the root panel get­ting detached from the DOM so that I can final­ize my appli­ca­tion. Sur­pris­ingly, that does not work in Chrome (tested Chrome and Fire­fox only).

    But besides that this sounds like a bug to me, I found the “proper” way of doing things before the appli­ca­tion ends:

    Window.addWindowClosingHandler(new Window.ClosingHandler() {
    	@Override public void onWindowClosing(ClosingEvent event) { ... }
    });

    In the end, I think some­thing like Document.addUnloadHandler would be more sug­ges­tive… clos­ing the win­dow or reload­ing a page is both exit­ing the appli­ca­tion by unload­ing the DOM — not clos­ing the window.

    18 Feb 2011, 1:27pm
    gwt:

    1 comment




  • Disable an Anchor in GWT

    Unex­pect­edly, call­ing setEnabled(false) does not pre­vent a link/anchor from being clicked. That means, the click events still get trig­gered.
    The rea­son is more or less a bug in GWT as it updates the list of events that are going to be trig­gered only at the moment when it gets attached to the DOM (Btw, in GWT, this process is called to sink and to unsink events, where the for­mer enables a spe­cific event to be trig­gered and the lat­ter dis­ables it).
    I found a workaround by cre­at­ing my own Anchor class and forc­ing the under­ly­ing GWT Anchor to update the list of events to be sunk.

    ...
    import com.google.gwt.event.dom.client.ClickHandler;
    import com.google.gwt.user.client.Event;
    
    public class Anchor extends com.google.gwt.user.client.ui.Anchor {
    
    	@Override public void setEnabled(boolean enabled) {
    		super.setEnabled(enabled);
    		if (isAttached()) {
    			onDetach();
    			if (enabled) {
    				sinkEvents(Event.ONCLICK);
    			} else {
    				unsinkEvents(Event.ONCLICK);
    			}
    			onAttach();
    		}
    	}
    
    	@Override protected void onLoad() {
    		super.onLoad();
    		if (isEnabled()) {
    			sinkEvents(Event.ONCLICK);
    		} else {
    			unsinkEvents(Event.ONCLICK);
    		}
    	}
    }

    Note the onLoad method, it sets up the state when the wid­get gets attached to the DOM the first time. It is required because setEnabled() could have been called before the anchor got attached.

    If you encoun­tered the same issue, please vote for this bug report.

    4 Feb 2011, 10:10pm
    gwt:

    leave a comment




  • Disable Context Menu in GWT

    To make use of the right mouse but­ton, it is nec­es­sary to dis­able the native browser con­text menu (the popup menu appear­ing on right click). This can be achieved like this:

    RootLayoutPanel.get().addDomHandler(new ContextMenuHandler() {
    
    	@Override public void onContextMenu(ContextMenuEvent event) {
    		event.preventDefault();
    		event.stopPropagation();
    	}
    }, ContextMenuEvent.getType());

    Same should work for RootPanel.

    After that, it is pos­si­ble to make use of the right mouse but­ton for exam­ple like this:

    someWidget.addDomHandler(new MouseMoveHandler() {
    
    	@Override public void onMouseMove(MouseMoveEvent event) {
    		if (event.getNativeButton() == NativeEvent.BUTTON_RIGHT) {
    		...
    2 Feb 2011, 11:45pm
    gwt jobs:

    leave a comment




  • GWT Error Message “Asked for attribute parser of no type”

    Exam­ple:

    public boolean isCollapsed() {
    	return panel.isVisible();
    }
    
    public void setCollapsed() {
    	panel.setVisible(false);
    }

    Seen it? Despite the com­pli­cated and cryp­tic error mes­sage, the mis­take is rather sim­ple: the set­ter method is miss­ing a para­me­ter, i.e. “pub­lic void setCollapsed(boolean collapsed) {“.

    17 Jan 2011, 6:38pm
    gwt jobs:

    leave a comment




  • Testing GWT Application in Virtual Machine

    I am devel­op­ing on a Mac, but to test my GWT appli­ca­tions for cross-browser com­pat­i­bil­ity in Inter­net Explorer I need to use Win­dows, thus I got Win­dows 7 installed using Par­al­lels. Just by the way, to be able to test in dif­fer­ent Inter­net Explorer ver­sion, I am using a pretty handy appli­ca­tion called IETester.
    But try­ing to access local­host with IE in the vir­tual machine did not work. I got a “404 page not found” error instead of see­ing my app run­ning on the local App Engine instance. Obvi­ously, Par­al­lels does not auto­mat­i­cally for­ward local­host requests to OSX and maybe that is actu­ally a good idea security-wise.
    To fix the issue, you need to run Google App Engine on a pub­lic net­work inter­face, or in other words, bind the App Engine server to all avail­able IP addresses. The down side: every­body know­ing your IP address can see the GWT app now, but oth­er­wise you are not allowed to access it in the viru­tal machine as from your OSX’s point of view, that Win­dows machine is “some other guy access­ing from the out­side”, too. To make GAE acces­si­ble from the out­side, add the para­me­ter “-bindAd­dress 0.0.0.0″ when launch­ing you local GAE. Using Eclipse you can achieve that by right click­ing your project -> Run As -> Run Con­fig­u­ra­tions -> Choose “(x)= Argu­ments” tab; add the option to the top most box titled “Pro­gram argu­ments” in the options area (e.g. before “-port 8888″).

    The first part of the list of argu­ments should look some­thing like that:

    -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -startupUrl GlocalUiPg2.html -logLevel INFO -codeServerPort 9997 -bindAddress 0.0.0.0 -port 8888 ...

    Now, you can access you app using the OSX’s pub­lic IP address. (You can get to know your IP by hav­ing a look at the net­work pref­er­ences panel.) Launch­ing GAE from Eclipse, you will see a dif­fer­ent link (URL) in the “Devel­op­ment Mode” tab now, con­tain­ing the pub­lic IP already. Using that one in, say, your Fire­fox on Mac, it will ask you now whether you want to allow the debug­ger access. That is also due to the fact, that you are now using a pub­lic address, so it is not clear to your local debug server, whether that request came from the same com­puter or some­one else in the network.

    3 Dec 2010, 4:02pm
    gwt:

    leave a comment




  • Adding a New Service (GWT)

    Adding a new servlet/service to you GWT appli­ca­tion is quite straight for­ward, e.g. by copy­ing the exam­ple “greet­ingSer­vice” or cre­at­ing a new servlet. But it’s easy to over­look a required change/adjustment of your project’s con­fig­u­ra­tion and you might end up with an error mes­sage like “Blocked attempt to access inter­face ‘some.package.SomeService’, which is not imple­mented by ‘some.other.package.SomeOtherServiceImpl’; this is either mis­con­fig­u­ra­tion or a hack attempt”.

    Check list (some should be replaced with what­ever you want to call your new service):

    • Copy or cre­ate files:
      SomeService.java and SomeServiceAsync.java in client pack­age
      SomeServiceImpl.java in server pack­age + change imple­men­ta­tion state­ment to SomeSer­vice
    • Adjust web.xml:
      <servlet>
      	<servlet-name>someServlet</servlet-name>
      	<servlet-class>some.package.SomeServiceImpl</servlet-class>
      </servlet>
      <servlet-mapping>
      	<servlet-name>someServlet</servlet-name>
      	<url-pattern>/[copy base directory name from other service declaration]/some</url-pattern>
      </servlet-mapping>
    • Anno­tate inter­face SomeService.java:
      @RemoteServiceRelativePath("some")
    • Con­nect to your new ser­vice in the client:
      private final SomeServiceAsync someService = GWT.create(SomeService.class);

    Def­i­nitely some pos­si­bil­i­ties to make a mis­takes or miss some­thing here.

    17 Sep 2010, 4:16pm
    jobs projects:

    1 comment




  • Using the XML Parser in GWT

    I tried using the XML pars­ing fea­tures of the GWT like that:

    form.addSubmitCompleteHandler(new SubmitCompleteHandler() {
    	@Override
    	public void onSubmitComplete(SubmitCompleteEvent event) {
    		// One time upload only, to upload again, user needs to start the upload process from scatch – keeping it simple for now
    		panel.clear();
    		Window.alert(event.getResults());
    		Document result = XMLParser.parse(event.getResults());
    		...
    });

    But GWT kept telling me “No source code is avail­able for type com.google.gwt.xml.client.Document; did you for­get to inherit a required mod­ule?”. It turns out, you are required to explic­itly add the XML func­tion­al­i­ties to your project by adding fol­low­ing line to your .…gwt.xml file:

    <inherits name='com.google.gwt.xml.XML'/>

    Raises a ques­tion: What’s the point of AJAX (Asyn­chro­nous JavaScript and XML) with­out XML? Or in other words there is no AJAX with­out XML! So it’s up to you to add the AX part to GWT man­u­ally. What’s next?

    16 Sep 2010, 6:02pm
    jobs projects:

    3 comments




  • GWT FileUpload: Adding Widgets to a FormPanel

    If you build your first GWT form, for exam­ple some­thing like that:

    <!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">
    <g:HTMLPanel>
    <g:FormPanel ui:field="form"> 
    <g:FileUpload ui:field="uploadField" name="file"/>
    <g:SubmitButton ui:field="submitButton">Upload</g:SubmitButton>
    </g:FormPanel>
    </g:HTMLPanel>
    </ui:UiBinder>

    And your con­sole keeps telling you dur­ing run­time some­thing like this: “java.lang.IllegalStateException: Sim­plePanel can only con­tain one child wid­get”. Instead of writ­ing a long page of expla­na­tions and com­plaints like I did before, it’s sim­ply like that:

    Just put all your wid­gets in a panel (like Hor­i­zon­tal­Panel) and add that panel to the Form­Panel.” (Jake − cf. com­ment below)

    Thanks Jake! :)

    9 Sep 2010, 4:48pm
    jobs projects:

    1 comment




  • GWT Does Not Load Module in Local AppEngine

    The issue arose after I renamed the mod­ule file (end­ing with .gwt.xml) to bet­ter rep­re­sent the mod­ule func­tion­al­ity. I also updated all rel­e­vant files in the project (search for files con­tain­ing the old name to find them) accordingly.

    Start­ing the appli­ca­tion after that mod­i­fi­ca­tions ended up in an error (“[ERROR] Unable to find ‘<old mod­ule name>.gwt.xml’ on your class­path; could be a typo, or maybe you for­got to include a class­path entry for source?”) as the AppEngine tried load­ing the mod­ule by its old name.

    Solu­tion: Delete the launch pro­file for the project (by choos­ing “Run As…” -> “Run Con­fig­u­ra­tions…” from the con­text menu).

    Obvi­ously the GWT does not check nor update the auto­mat­i­cally gen­er­ated launch pro­file thus you need to delete it to force the GWT to cre­ate a new pro­file from scratch tak­ing the project changes into account. You might also adjust the pro­file accord­ing to the changes made, but delet­ing it is the safe and easy way.

    25 Aug 2010, 10:41am
    jobs projects:

    leave a comment




  • First GWT Steps

    Just started to work with GWT – a pretty inter­est­ing approach for web devel­op­ment com­pared to PHP or JSF. The whole Appli­ca­tion engine is quite impres­sive espe­cially allow­ing you to quickly test your appli­ca­tions locally by sup­port­ing auto­matic hot deploy­ment after each code update.
    One thing that took me a while was one of that “[ERROR] Unable to find ‘[some-file].xml’ on your class­path; could be a typo, or maybe you for­got to include a class­path entry for source?” errors. If you are sure the file is in place, I real­ized restart­ing the App Engine or Eclipse mostly solves that problem.