Skip to content

All posts by moore - 82. page

Step #2: A Calculator which retrieves data from a Java server process

(Updated 6/14 with links to the two parts of this step)

The next step in building a real world mortgage calculator using GWT is to retrieve something simple from a back end. (See the problem’s introduction and Step #1, as well as the client code and the server code portions of the step described below.) It will be easiest to start with something simple. In this example, the client will pull two different mortgage interest rates (a 30 year fixed rate and a 5/25 ARM rate) from the Expresso back end. Since I am accessing a Java back end, there are two options.

  • Google’s services infrastructure. The benefit of this is fairly painless and transparent marshaling of Java value objects–that’s according to the documentation, I haven’t used it. The main downside is that I can’t use Expresso’s default servlet (with its authentication, logging, and caching) to handle the service request, because you must always extend Google’s RemoteServiceServlet.
  • Use the HTTPRequest
    class. This class essentially wraps the XMLHttpRequest object in a cross browser way, so if you’re familiar with that Javascript construct (which is at the heart of AJAX), the API shouldn’t be too shocking. This class limits the types of response available; no XML/DOM tree is passed back from a request, just text (in a String). The benefit of this method is that it’s very familiar to folks who’ve used XMLHttpRequest and is relatively simple. The main downside is that you’re limited to Strings as return values. There are, however, ways around that limit.

Based on the current requirements, it made more sense to use HTTPRequest than Google services. I could see using the Google services layer if I were doing some green field development in Java, or in a situation where such transparent marshaling saved a significant deal of work.

Of course, when you’re sending back text, you have a couple of options for encoding the data. I considered a custom encoding, but that’s not very scalable to large datasets, escaping and unescaping can be non trivial, and there are well known text transfer formats out there. Of those I know, XML and JSON are the primary ones. I went with JSON because Google kindly (almost) provides a JSON parsing library in their sample code. This parsing library is nice because it allows me to send back values as Strings, Arrays, Booleans, Numbers or Objectss and converts the JSON to the appropriate type. I say almost because I had to make a few changes to their code.

In my next post, I’ll look at the server side changes I made, including integrating the JSON.Simple Java library into Expresso.

Step #1: A Calculator with No Server Interaction

(Update 6/26: Here’s step #2, step #3 and the conclusion, with more source code.)

The first step is to build a simple javascript mortgage calculator, like many others out there, but using GWT. It seems that GWT is a great way to build complicated JavaScript UIs without much knowledge of JavaScript. (As an aside, I know this first solution is vastly overengineered, but eventually the problem set will require more of GWT.)

If you’re in a hurry, the GWT Mortgage Calculator is live and here is the source (for eclipse, for Windows; you’ll need to download the GWT and place the libraries in the lib subdirectory).

First, I found this article about calculating loan payments, which seemed straightforward enough. Then I downloaded the GWT and played around with some of the examples. I then created a project for eclipse, using the instructions in the GWT getting started guide.

A mortgage calculator is a pretty simple problem, really. Five labels and text boxes cover the needed inputs and outputs for interest rate, loan amount, term, number of payments and paymount amount. Also needed is a ‘calculate’ button and some way of conveying an error, should the user give invalid input.

I looked at using HorizontalPanel and VerticalPanel, but they looked horrible. I ended up using a FlexTable, which worked just fine.

I wanted to do some inline validation on the textboxs to make sure no one was entering anything other than numbers and a decimal point. Luckily, there is sample code for doing just this. This code worked just fine when I was running in my hosted environment, but when I deployed to a server and looked at the calculator in FireFox, I couldn’t type anything. The Google Web Toolkit group had the answer:

The problem is that GWT does not handle the the way that Mozilla/Firefox uses keyCode. For a key press event, evt.keyCode is only set for the non-character codes (Function keys, PageUp etc). For character keys the evt.charCode field is set. For key up/down events evt.charCode is never set, only evt.keyCode.

After disabiling this input validation, the calculator worked on FF.

I started out using a popup for error conditions, like non numeric user input. This examples is wrong–rather than setWidget() as the last line of the constructor, you need add(), otherwise you end up seeing an error like this:

[ERROR] Uncaught exception escaped
java.lang.RuntimeException: JavaScript method '@
com.google.gwt.user.client.ui.impl.PopupImplIE6::fixup
(Lcom/google/gwt/user/client/Element;)'
threw an exception
at com.google.gwt.dev.shell.ie.ModuleSpaceIE6.invokeNative(
ModuleSpaceIE6.java:394)
at com.google.gwt.dev.shell.ie.ModuleSpaceIE6.invokeNativeVoid(
ModuleSpaceIE6.java:283)
at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeVoid(
JavaScriptHost.java:127)
at com.google.gwt.user.client.ui.impl.PopupImplIE6.fixup(
PopupImplIE6.java:43)
at com.google.gwt.user.client.ui.PopupPanel.show(PopupPanel.java:211)

(More information here.) I ended up using a dialog box instead, because I felt it looked better.

Now I had a working copy of the MortgageCalculator, and I just needed to integrate it into my client's website. For speed, we decided I'd just check the derivative javascript/html/xml into the site's source tree. Obviously, for the long term this is not a viable solution. A better way to do this would be to store the java files (and libraries, etc) in CVS and use some of the ant integration out there. Eventually we'll get there.

For ease of integration, I added a paragraph element to an existing JSP with a unique ID that the java class will reference and into which the java class will push the generated html (updated 6/13 to fix a broken url). This is just like the sample application.

In order to access the javascript when the including file and the generated javascript are not in the same directory, you need to not only modify the src attribute from <script language="javascript" xsrc="gwt.js" mce_src="gwt.js"></script> to <script language="javascript" xsrc="/absolute/path/to/gwt.js" mce_src="/absolute/path/to/gwt.js"></script> but also the meta tag. This tag changes from <meta name='gwt:module' content='com.cohomefinder.gwt.mortgagecalculator.MortgageCalc'> to <meta name='gwt:module' content='/absolute/path/to/com.cohomefinder.gwt.mortgagecalculator.MortgageCalc'>. This tag can actually be placed in the body rather than in the head.

I ran into another issue when integrating this code into the existing website. For some reason, in FireFox 1.5.0.4 the error dialog box doesn't show up where it should, and instead is placed at the bottom of the screen. Here is the relevant section of code:

if (retVal != 0) {
ErrorDialog err = new ErrorDialog("v1 Please enter all data in n
umeric format.");
Widget slot1 = RootPanel.get("slot1");
int left = slot1.getAbsoluteLeft() + 10;
int top = slot1.getAbsoluteTop() + 10;
err.setPopupPosition(left, top);
err.setStyleName("error-Popup");
err.show();
}

and here's the error message from the Javascript Console:

Error: Error in parsing value for property 'left'.  Declaration dropped.
Source File: http://localhost:8080/Colorado-mortgage.htm Line: 0
Error: Error in parsing value for property 'top'.  Declaration dropped.
Source File: http://localhost:8080/Colorado-mortgage.htm Line: 0

This seemed to occur no matter which widget I was trying to get the absolute position of--the button, the enclosing table, or the enclosing paragraph element. This only occurred when integrating the calculator into a JSP page (not in the generic generated html), so it's likely it was a site specific bug. To work around it, I used a label rather than a dialog box.

Other random tidbits:

  • In general, I was less than impressed with the Google provided documentation, but very impressed with the GWT group.
  • It was very easy to quickly develop using Eclipse and the hosted web browser.
  • The HTML of the file you're developing to lives under the src directory (all the way down in the public folder).
  • All the javascript and html are compiled into the www directory.

Next, we're going to integrate with Expresso and pull some values from the database.

Step by Step: A Mortgage Calculator using GWT

The following couple of posts are a first for my blog. I have blogged about client projects before, but never have I been paid to do so. But, I currently have a client who enjoys my blog. He also is a big fan of the Google Web Toolkit, and is interested in exploring the usefulness of this toolkit to his website, Colorado HomeFinder (Updated 6/10 with the name of the client, per his request). (Disclaimer: everything I say on this blog is my fault and mine alone.)

So, in the interest of exploration, I’m going to be building a simple mortgage calculator. We’ll be using GWT 1.0.21, developing on Windows XPSP2 and integrating with a existing backend built using Expresso 5.3, a heavyweight open source framework. (I’ve used Expresso before, and written about it, and while the framework is not without its warts, it can be very useful.) I will also be using Eclipse 3.1 to build the code, and be deploying to Linux. FireFox 1.5.0.4 and IE 6.0 (both on Windows XPSP2) will be used to test the application.

I’ll be documenting my missteps and lessons learned as I go. In addition, the client has kindly offered to let me distribute the source on my website, so I’ll be providing a download each step of the way.

Update, Aug 9: Here’s a list of what I’ve written:

Google does spreadsheets

Check out spreadsheets.google.com. Limited time look at what javascript can do for a spreadsheet. I took a quick look and it seems to fit large chunks of what I use Excel or calc, the OpenOffice spreadsheet program, for. Just a quick tour of what I such spreadsheet programs for, and what Google spreadsheet supports:

  • cut and paste, of text and formulas
  • control arrow movement and selection
  • formatting of cells
  • merging of cells and alignment of text in cells
  • undo/redo that goes at least 20 deep
  • sum/count
  • can freeze rows
  • share and save the spreadsheet
  • export to csv and xls

On the other hand, no:

  • dragging of cells to increment them (first cell is 45, next is 46, 47…).
  • using the arrows to select what goes into a formula–you can type in the range or use the mouse

Pretty decent for a web based application. And it does have one killer feature–updates are immediatly propagated (I have never tried to do this with a modern version of Excel, so don’t know if that’s standard behaviour). Snappy enough to use, at least on my relatively modern computer. I looked at the js source and it’s 55k of crazy javascript (Update, 6/9: This link is broken.). Wowsa.

I’ve never used wikicalc but it looks more full featured that Google spreadsheets. On the other hand, Google spreadsheets has a working beta version…

This and the acquisition of writely make me wonder if some folks are correct when they doubt that Google will release a software productivity suite. (More here.) Other interesting comments from Paul Kedrosky.

I know more than one person that absolutely depend on gmail for business functionality, which spooks me. And in some ways, I agree with Paul, it appears that Google “…takes a nuclear winter approach wherein it ruins markets by freezing them and then cutting revenues to zero.”

Personally, if I don’t pay for something, I’m always leery of it being taken away. Of course, if I pay, the service can also go away, but at least I have some more leverage with the company–after all, if they take the service away, they lose money.

Bloglines and SQL

I moved from my own personal RSS reader (coded in perl by yours truly) to Bloglines about a year ago. The main reason is that Bloglines did everything my homegrown reader did and was free (in $ and in time to maintain it).

But with over 1 billion articles served as of Jan 2006, I always wondered why Bloglines didn’t do more collaborative filtering. They do have a ‘related feeds’ tab, but it doesn’t seem all that smart (though it does seem to get somewhat better as you have more subscribers). I guess there are a number of possible reasons:

  • It’s easier to find feeds that look like they’d be worth reading (I have 180 feeds that I attempt to keep track of)
  • blogrolls provide much of this kind of filtering at the user level
  • privacy concerns?
  • No demand from users

But this article, one of a series about data management in well known web applications, gives another possible answer: the infrastructure isn’t set up for easy querying. Sayeth Mark Fletcher of bloglines:

As evidenced by our design, traditional database systems were not appropriate (or at least the best fit) for large parts of our system. There’s no trace of SQL anywhere (by definition we never do an ad hoc query, so why take the performance hit of a SQL front-end?), we resort to using external (to the databases at least) caches, and a majority of our data is stored in flat files.

Incidentally, all of the articles in the ‘Database War Stories’ series are worth reading.

Using Grids?

Tim Bray gives a great write up of Grid Infrastructure projects. But he still doesn’t answer Stephen’s question: what is it good for?

I think the question is especially relevant for on demand ‘batch grids’, to use Tim’s terms. A ‘service grid’ has uses that jump to mind immediately; scaling web serving content is one of them. But on demand batch grids (I built an extremely primitive one in college) are good for complicated processes that take a long time. I don’t see a lot of that in my current work–but I’m sure my physics professor would be happy to partake.

Verifying the state of an image download in an javascript event

Well, I was going to write a rant, explaining how as far as I could tell, there was no way to make sure an image was downloaded, or degrade gracefully if it wasn’t–within an event like onclick. But, it all boils down to the fact that there is no Thread.sleep() equivalent in javascript. See this for a fine explication or read on for an overview of what I tried that failed.

The problem is that the only real way to do it in javascript is to use setTimeout (Mozilla docs, IE docs). The problem with setTimeout is that after calling it, your event handling code merrily continues to execute, and that your setTimeout callback will probably not finish before the event code is finished.

The other way I thought of was to loop waiting for a specified number of seconds (like this). Unfortunately, in my tests, the javascript engine in IE6 doesn’t appear to be multithreaded, and while this wait code executes, the image is not being downloaded.

I did not try the modal window approach, or the java applet (which seems a bit like using a sledgehammer to hit a mosquito) outlined here, but I’m not sure that either of those is really production ready (I’m not alone).

Familiarity Breeds Content

With tools, at least.

James Governor raises an interesting question: Is Smalltalk Set for a Renaissance. He discusses some of the new things that are being built on this old language.

However, the most interesting thing to me is his comment, the title of this post, that ‘familiarity breeds content’ for tools. I’ve touched on this 2 years ago, when I wrote why I thought struts would be around for a good while. Incidentally, history has shown me out–currently there are 1958 hits on dice for ‘struts’, compared to 58 for ‘webwork’ and 29 for ‘ruby on rails’. (Past performance is no guarentee of future results…)

Of course, that’s no judgement on the benefits of the tools; badly written cgi scripts are still around too. In fact, part of a developer’s job, I believe, is to at least play around with new tools and options that may make them more productive. The important takeaway is that, just as many users are reluctant to change office suites, even to upgrade, many developers have enough on their plates without learning new tools.