{"id":353,"date":"2006-06-14T20:02:28","date_gmt":"2006-06-15T02:02:28","guid":{"rendered":"http:\/\/www.mooreds.com\/wordpress\/?p=353"},"modified":"2007-01-27T19:04:56","modified_gmt":"2007-01-28T01:04:56","slug":"step-2b-updating-the-gwt-client-to-communicate-with-the-server","status":"publish","type":"post","link":"https:\/\/www.mooreds.com\/wordpress\/archives\/353","title":{"rendered":"Step #2b: Updating the GWT Client to communicate with the Server"},"content":{"rendered":"<p>The next step is to update the client to communicate with the server side components.  Again, if you&#8217;re not very patient, you can see the live client code at <a href=\"http:\/\/www.cohomefinder.com\/Colorado-mortgage.htm\">Colorado HomeFinder<\/a>, and <a href=\"http:\/\/www.mooreds.com\/files\/mtgcalc-v2.tar.gz\">download the source<\/a>.<\/p>\n<p>I need to add a drop down, which will offer users the option of a 5\/25 ARM rate, or a 30 year fixed rate.  I need to have some way of decoding the JSON response from the server, and I need to update the interest rate text box with the results from the server.<\/p>\n<p>Adding the drop down is fairly easy: Google provides <a href=\"http:\/\/code.google.com\/webtoolkit\/documentation\/com.google.gwt.user.client.ui.ListBox.html\">a listbox<\/a>.  The listbox is an instance variable, rather than a local variable, and I also change the interest text box from a local variable to an instance variable.  The reason: the change listener, which is a non static member  class, has easier access to an instance variable than to a local one.  Here&#8217;s the relevant code:<\/p>\n<pre>rateChoiceBox.addItem(\"5\/25 ARM\");\r\nrateChoiceBox.addItem(\"30 Year Fixed\");\r\nrateChoiceBox.setVisibleItemCount(1);\r\nrateChoiceBox.setWidth(width);\r\nfinal RatesResponseHandler rrh = new RatesResponseHandler();\r\nHTTPRequest.asyncGet(RATES_URL, rrh);\r\n\r\nrateChoiceBox.addChangeListener(new ChangeListener(){\r\npublic void onChange(Widget sender) {\r\nHTTPRequest.asyncGet(RATES_URL, rrh);\r\n}\r\n}\r\n);\r\n...\r\nprivate class RatesResponseHandler implements ResponseTextHandler {\r\n\r\npublic void onCompletion(String responseText) {\r\nboolean keepGoing = true;\r\nJSONObject jso = null;\r\ntry {\r\njso = JSONParser.parse(responseText);\r\n} catch (JSONException je) {\r\nkeepGoing = false;\r\n\/\/ not sure what to do\r\n}\r\nString rate = \"\";\r\n\/\/ ... get the data, put it into the rate variable.\r\nMortgageCalc.this.interest.setText(rate);\r\n}\r\n}<\/pre>\n<p>In the <code>RatesResponseHandler<\/code>, I try to parse the JSON response that has been asynchronously downloaded from the server, and if I get meaningful text, I set the interest rate in the textbox: <code>MortgageCalc.this.interest.setText(rate);<\/code>  If the server is not available, we still have a sane default.  One interesting item: when you run the code with the server off in development, GWT pops you into the MS script debugger, which at least lets you know something is wrong.<\/p>\n<p>The JSON processing code has already been written, so it made sense to leverage the <a href=\"http:\/\/code.google.com\/webtoolkit\/documentation\/examples\/jsonrpc\/\">JSON example<\/a> that Google kindly provided.  To do this, I made a few changes. Luckily, all the example code is made available under the <a href=\"http:\/\/www.apache.org\/licenses\/LICENSE-2.0\">Apache 2.0 license<\/a>. You can find json.jar in the download, should you want to use it for a project of your own.<\/p>\n<p>First, I wanted to make sure that none of the behavior of the <code>EntryPoint<\/code> JSON class occurred&#8211;I wanted the subsidiary libraries, but not the <a href=\"http:\/\/code.google.com\/webtoolkit\/documentation\/examples\/jsonrpc\/demo.html\">potato demostration<\/a>.  Therefore,  I eviscerated the JSON class, and gave it an empty <code>onModuleLoad<\/code> method.  On reading the <a href=\"http:\/\/code.google.com\/webtoolkit\/documentation\/com.google.gwt.doc.DeveloperGuide.Fundamentals.Modules.html\">module documentation<\/a>, it appears this wasn&#8217;t needed&#8211;I could have just eliminated the <code>&lt;entry-point&gt;<\/code> entry.<\/p>\n<p>Then, I started building the JSON code library.  To pull in a set of external widgets, you need to do a couple of things.<\/p>\n<ol>\n<li>Build the library.  I did this by compiling the JSON source, from the samples directory: <code>mkdir builddir && javac -d builddir -classpath `cygpath -wp $PWD\/bin\/:.:..\/..\/..\/gwt-windows-1.0.21\/gwt-user.jar` src\/com\/google\/gwt\/sample\/json\/client\/JSON*.java<\/code>. (The cygpath stuff is there because I&#8217;m developing on cygwin.) One thing to remember&#8211;you need to copy the java files into that same build directory: <code>cd builddir\/com\/google\/gwt\/sample\/json\/client && cp ..\/..\/..\/..\/..\/..\/src\/com\/google\/gwt\/sample\/json\/client\/*.java .<\/code>. (Apparently you need the .class files for Eclipse or any other IDE, and you need to .java files so the Google compiler can compile the java to javascript.  <a href=\"http:\/\/groups.google.com\/group\/Google-Web-Toolkit\/browse_thread\/thread\/c5660c9912ffdda\/ebe0912f86ff586f?q=inherit&#038;rnum=2#ebe0912f86ff586f\">More here<\/a>.)   Also, don&#8217;t forget the JSON.gwt.xml, which should go in <code>builddir\/com\/google\/gwt\/sample\/json<\/code>.<\/li>\n<li>Jar up the code, and place it in the classpaths.  To compile from the command line, I added it to the <code>Mortgage-compile.cmd<\/code> batch file.  For Eclipse development, I added it to the project buildpath (<a href=\"http:\/\/www.awprofessional.com\/articles\/article.asp?p=367962&#038;rl=1\">instructions for doing so<\/a>).  And I also had to add the json.jar file to the MortgageCalc application, so I could debug in Eclipse.  To do this, choose &#8216;Run&#8217; from the top menu, choose the &#8216;Run&#8230;&#8217; option, select &#8216;MortgageCalc&#8217;, click the &#8216;Classpath&#8217; tab, click &#8216;User Entries&#8217; and add the jar using the Add button.<\/li>\n<li><a href=\"http:\/\/code.google.com\/webtoolkit\/documentation\/com.google.gwt.doc.DeveloperGuide.Fundamentals.Modules.ModuleXml.html\">Inherit from the JSON module<\/a>.  As far as I can tell, this isn&#8217;t inheritance in the usual object oriented sense, it&#8217;s more like importing packages in java. I did this by adding this line to the MortgageCalc.gwt.xml: <code>&lt;inherits name='com.google.gwt.sample.json.JSON'\/&gt;<\/code> (I did try to use a source path to refer to the JSON classes, rather than inherit from them, but got this error:<br \/>\n<blockquote><p>[WARN] Non-canonical source package: ..\/..\/..\/google\/gwt\/sample\/json\/client\/<br \/>\n&#8230;<br \/>\n[ERROR] Unable to find type &#8216;com.cohomefinder.gwt.mortgagecalculator.client.MortgageCalc&#8217;<br \/>\nHint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly<\/p><\/blockquote>\n<p>)<\/li>\n<\/ol>\n<p>After going through those steps, I could use the <code>JSONParser<\/code> and other JSON objects in my widget.  Here&#8217;s the balance of the <code>RateResponseHandler<\/code>:<\/p>\n<pre>if (keepGoing && jso != null) {\r\nint selected = MortgageCalc.this.rateChoiceBox.getSelectedIndex();\r\nString [] keys = jso.getKeys();\r\nif (keys.length == 2) { \/\/ expected\r\nJSONValue jsvrate =\r\njso.get(keys[selected]);\r\nJSONString jsstr = null;\r\nif ((jsstr = jsvrate.isString()) != null) {\r\nString rate = \"\";\r\nif ((rate = jsstr.toString()) !=\r\nnull) {\r\n\/\/Window.alert(\"rate:\r\n\/\/\"+rate);\r\nMortgageCalc.this.interest.setText(rate);\r\n\r\n}\r\n}\r\n}\r\n}<\/pre>\n<p>The JSON parsing code is rather verbose.  I also wasn&#8217;t a fan of the return values from the <code>is*<\/code> methods; I was always told that any method prefixed with &#8216;is&#8217; should return a boolean.  But then I peeked into the <code>JSONParser<\/code> class and decided that I&#8217;d just use the free code<br \/>\nand stop complaining.  Final comments:<\/p>\n<ul>\n<li>The module inheritance system is a quite powerful, if slightly<br \/>\nmisnamed, method of reusing code.  In fact, there is already at least one <a href=\"http:\/\/gwtwidgets.blogspot.com\/\">blog about GWT widgets<\/a>.<\/li>\n<li>Packaging up code for a module is tedious, and perfectly suited to an<br \/>\nant task.<\/li>\n<li>HTTPRequest is entirely adequate for pulling down data.<\/li>\n<li>JSON, combined with HTTPRequest, gives you some typing, without tying<br \/>\nyou into a custom servlet.  If you want typing stricter or more granular<br \/>\nthan <a href=\"http:\/\/javascript-reference.info\/#type\">javascript<br \/>\nprovides<\/a> and are using a java backend, then <a href=\"http:\/\/code.google.com\/webtoolkit\/documentation\/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.CreatingServices.html\">Google&#8217;s<br \/>\nservices<\/a> might be a better choice.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>The next step is to update the client to communicate with the server side components. Again, if you&#8217;re not very patient, you can see the live client code at Colorado [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,6],"tags":[],"class_list":["post-353","post","type-post","status-publish","format-standard","hentry","category-gwt","category-programming"],"_links":{"self":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/353","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/comments?post=353"}],"version-history":[{"count":0,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/353\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/media?parent=353"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/categories?post=353"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/tags?post=353"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}