gwt


Its been a crazy December through January and I haven’t written much!

I’m glad the GWT posts helped some of you from the comments. I spent some time on figuring them out from the limited docs on google’s GWT site, mostly I think it helps to have complete examples since they dont make it real clear what file each snippit of code goes in. I’m glad the pain I went through to figure them out help some of you :) A few of you had problems but i haven’t gotten around to seeing what is wrong. I was using the trunk version of GWT, so if you are using 2.0 then you might have some differences.

I’ve been diving my head back into rails after spending a spell in perl/mason and GWT in some projects for work. I think other languages are neat but I really love ruby. So I’ve been re-watching some of my episodes of PeepCode.com and RailsCasts.com those guys are awesome. I love this stuff. Why else would I be spending my Saturday night with Ruby vs watching a movie or playing a game!

I’ve also been playing with android a bit, its pretty fun to see my app on a phone! Working on a TODO List app, which seems almost like “hello world” but it has a twist… more later when i have something to show.

Been working learning jQuery. I had seen it before, but saw class names mixed with programming and having a ugghhhh feeling. But.. I decided to give it a shot and dang! I would have given my right arm to have this 5 years ago when i was experimenting with ajax (though it wasn’t called that…) with setting the src of a script tag with a php url to load and save data. Anyways, its cool and neat. I think the name is horrible since you aren’t really quering anything… IMHO :) Maybe if I can think of a better one I can suggest it, but seems like it is here to stay since there are stay since there are 4 books already about it!

To help with reviewing ruby I have been working through Ruby Koans. Hats off to EdgeCase. I have already written them and thanked them! This goes along with my post How To Get Better At Programming where I wrote about how i was working at getting better at programming. It all comes down to practice! … I think when I finish the rubykoans exercises, i will revert and start going through them again. Almost like doing pushups every day (I push up to get more coffee at least 3x a day!).

Git … I did my first pull request on github, very cool how that works.

Have some ideas for some more substantial posts… coming soon :)

I was pretty excited to find UiHandler, it makes the organization of code so much cleaner!

I am putting in the full code for both, so you can see the beauty for yourself! Pay attention to the comments where i put the gotchas that got me at first! :)
Before:

JAVA:
  1. package com.rubygeek.sandbox.client;
  2.  
  3. import java.util.ArrayList;
  4.  
  5. import com.google.gwt.core.client.GWT;
  6. import com.google.gwt.event.dom.client.ClickEvent;
  7. import com.google.gwt.event.dom.client.ClickHandler;
  8. import com.google.gwt.uibinder.client.UiBinder;
  9. import com.google.gwt.uibinder.client.UiField;
  10. import com.google.gwt.user.client.Window;
  11. import com.google.gwt.user.client.ui.Button;
  12. import com.google.gwt.user.client.ui.CheckBox;
  13. import com.google.gwt.user.client.ui.Composite;
  14. import com.google.gwt.user.client.ui.Widget;
  15.  
  16.  
  17. public class LanguageList extends Composite {
  18.  
  19.   interface MyUiBinder extends UiBinder<Widget, LanguageList> {}
  20.   private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
  21.  
  22.   @UiField CheckBox rubyCheck;
  23.   @UiField CheckBox pythonCheck;
  24.   @UiField CheckBox javaCheck;
  25.   @UiField CheckBox phpCheck;
  26.   @UiField Button button;
  27.  
  28.   public LanguageList() {
  29. // bind XML file of same name of this class to this class
  30. initWidget(uiBinder.createAndBindUi(this));
  31.  
  32. final ArrayList<CheckBox> boxes = new ArrayList<CheckBox>();
  33. boxes.add(rubyCheck);
  34. boxes.add(pythonCheck);
  35. boxes.add(javaCheck);
  36. boxes.add(phpCheck);
  37.  
  38. // add button and handler to alert the values of checkboxes
  39. button.addClickHandler(new ClickHandler() {
  40. public void onClick(ClickEvent event) {
  41. String output = "";
  42. for(CheckBox box : boxes) {
  43. if (box.getValue()) {
  44. output += box.getFormValue() + ", ";
  45. }
  46. }
  47. Window.alert("You checked: "+ output);
  48. }
  49. });
  50.  
  51.   }
  52. }

After:

JAVA:
  1. package com.rubygeek.sandbox.client;
  2.  
  3. import java.util.ArrayList;
  4.  
  5. import com.google.gwt.core.client.GWT;
  6. import com.google.gwt.event.dom.client.ClickEvent;
  7. import com.google.gwt.uibinder.client.UiBinder;
  8. import com.google.gwt.uibinder.client.UiField;
  9. import com.google.gwt.uibinder.client.UiHandler;
  10. import com.google.gwt.user.client.Window;
  11. import com.google.gwt.user.client.ui.CheckBox;
  12. import com.google.gwt.user.client.ui.Composite;
  13. import com.google.gwt.user.client.ui.Widget;
  14.  
  15. public class LanguageList extends Composite {
  16.  
  17.   interface MyUiBinder extends UiBinder<Widget, LanguageList> {}
  18.   private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
  19.  
  20.   final ArrayList<CheckBox> boxes = new ArrayList<CheckBox>();
  21.  
  22.   @UiField CheckBox rubyCheck;
  23.   @UiField CheckBox pythonCheck;
  24.   @UiField CheckBox javaCheck;
  25.   @UiField CheckBox phpCheck;
  26.  
  27.   // add ClickEvent handler to button with ui:field="languageButton" in the UiBinder code    
  28.   // !!! note no ; at end of this annotation, and the name of function does not matter, its the annotation that ties it to the
  29.   // body of the method, also this does not go inside the class :) (i spend 40 mins figuring that out...)
  30.   @UiHandler("languageButton")
  31.   void doClick(ClickEvent event) {
  32.       String output = "";
  33.       for(CheckBox box : boxes) {
  34.           if (box.getValue()) {
  35.               output += box.getFormValue() + ", ";
  36.           }
  37.       }
  38.       Window.alert("You checked: "+ output);
  39.  }
  40.  
  41.   public LanguageList() {
  42.       // bind XML file of same name of this class to this class
  43.       initWidget(uiBinder.createAndBindUi(this));
  44.       
  45.       boxes.add(rubyCheck);
  46.       boxes.add(pythonCheck);
  47.       boxes.add(javaCheck);
  48.       boxes.add(phpCheck);
  49.   }
  50. }

See the constructure is further slimmed down!

Note: as of right now, you can only get this feature in Trunk. see here for how to download the source and use it More Info on release

One of the great new features coming out of GWT 2.0 is UiBinder, a way to make a declarative UI without making tons of objects. Reminding you of swing? Yeah, I didn't sign up to be a Swing developer. I was sort of disturbed when I started doing gwt and was writing tons of java to just do simple HTML things.

Full Source

JAVA:
  1. CheckBox rubyCheck = new CheckBox("Ruby");
  2. rubyCheck.setFormValue("ruby");
  3. boxes.add(rubyCheck);
  4.  
  5. CheckBox pythonCheck = new CheckBox("Python");
  6. pythonCheck.setFormValue("python");
  7. boxes.add(pythonCheck);
  8.  
  9. CheckBox javaCheck = new CheckBox("Java");
  10. javaCheck.setFormValue("java");
  11. boxes.add(javaCheck);
  12.  
  13. CheckBox phpCheck = new CheckBox("PHP");
  14. phpCheck.setFormValue("php");
  15. boxes.add(phpCheck);
  16.  
  17. // set up panel
  18. Panel panel = new VerticalPanel();
  19. panel.add(new Label("Choose a language:"));

Compare to the UiBinder code:

XML:
  1. <ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
  2.     xmlns:g='urn:import:com.google.gwt.user.client.ui'>
  3.     <g:VerticalPanel>
  4.       <g:Label>Choose a language:</g:Label>
  5.       <g:CheckBox ui:field="rubyCheck" formValue="ruby">Ruby</g:CheckBox>
  6.       <g:CheckBox ui:field="pythonCheck" formValue="python">Python</g:CheckBox>
  7.       <g:CheckBox ui:field="javaCheck" formValue="java">Java</g:CheckBox>
  8.       <g:CheckBox ui:field="phpCheck" formValue="php">PHP</g:CheckBox>
  9.       <g:Button ui:field="button">Submit</g:Button>
  10.     </g:VerticalPanel>
  11. </ui:UiBinder>

It is somewhat like HTML, each item with attribute "ui:field=" is the reference to the object that gets created in Java. Here's the Java code that uses this:

Full Source

JAVA:
  1. public class LanguageList extends Composite {
  2.  
  3.   interface MyUiBinder extends UiBinder<Widget, LanguageList> {}
  4.   private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
  5.  
  6.   @UiField CheckBox rubyCheck;
  7.   @UiField CheckBox pythonCheck;
  8.   @UiField CheckBox javaCheck;
  9.   @UiField CheckBox phpCheck;
  10.   @UiField Button button;
  11.  
  12.   public LanguageList() {
  13.       // bind XML file of same name of this class to this class
  14.       initWidget(uiBinder.createAndBindUi(this));
  15.       
  16.       final ArrayList<CheckBox> boxes = new ArrayList<CheckBox>();
  17.       boxes.add(rubyCheck);
  18.       boxes.add(pythonCheck);
  19.       boxes.add(javaCheck);
  20.       boxes.add(phpCheck);
  21.   }

We still have to add them to the Array (which is use to display checked results) but doesn't that look so much better? And you are able to add the values of the checkboxes to the xml too.

When using UiBinder, make sure you add it as inherits to the xml for the module (i forgot at first and had errors with gwt trying to find UiBinder!)

I didn't do exactly one-to-one comparison between UiBinder and not, but i do have two complete gwt apps you can look at. I find it really helpful when learning something to look at complete apps rather than just snippits of code.

There is some documentation on Ui:Binder on Google Code, but at first I found it hard to follow since it doesn't say what files each piece goes in, it took me awhile to figure it out. Maybe its just me though. :)

Before UiBinder
After Ui Binder

Anyways, just a quick example that might help some people out there. I want to explore more about patterns in GWT and I'll write them up here.

Lately, I have been fascinated with Google Web Toolkit as of late. What you say, you love ruby but doing java?!!? My ruby friends will probably smack me but really i love all languages. The widgets and rpc stuff, that is pretty cool as well as learning how to do MVP. There are some new features in trunk that will be released "this fall" but I don't want to wait that long, so last night i set about to checkout and compile trunk and try it out!

1. I installed the latest version of eclipse Galileo, with the Google plugin
http://code.google.com/eclipse/

2. Checkout the source code
http://code.google.com/webtoolkit/makinggwtbetter.html#workingoncode
Make sure you have ant installed. It takes awhile, i think maybe 20 mins or so on my macbook.

3. Setup the API directory in the Preferences for GWT
It took a while (and many searches) of messing around to figure out how to switch to the trunk version of the API.

Go to Eclipse > Preferences. Find the Google Web Toolkit on the left. It has an interface to add/remove APIs. Click add, add the path like so:
~/gwt/trunk/build/lib
I named it "trunk"

4. Create project
Create a new Web Application Project, select "trunk" as the version of API. And now you are on your way!

Once i've done a little more with it, I'll write about some of the new features that are really awesome.