Skip to content

Programming - 12. page

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:

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.

JSVC and large log files

jsvc, which is used for daemoning Tomcat and other java applications on unix, takes filenames for stdout and stderr as arguments. One thing to be aware of is that when the either of these files reach a size of just over 2 gigabytes, jsvc simply fails. No error message. If you restart the application, it will note that it can’t write to the file and proceeds to write to the console. I saw this behavior using tomcat 5 on fedora core 4 with jsvc 1.0.1 (described here).

I am not sure exactly what the problem is, but when I started tomcat via the normal shell script, it was able to write to that file. The user that jsvc runs as had no limits on file size:

-bash-3.00$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
pending signals                 (-i) 1024
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 32764
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Therefore, it might be an issue with jsvc. Do note that there are nightly snapshots of jsvc, which might solve the issue. The solution I found is to use the copytruncate option of logrotate.

Code behaving badly

You know what, coding is hard. You’re balancing shifting requirements, a constant stream of new technologies and a hot cup of coffee, all while trying to keep up with your flood of email. When you actually get a minute to code, you sometimes don’t know where to start. Testing is important, but often gets shoved to the bottom of the priority list. This makes for some … interesting code. I love having my code reviewed, but it’s always a humbling experience.

That’s why The Daily WTF resonates with me. You know what? I’m self taught, so I probably have written code that bad. I just hope it wasn’t code someone paid me for. But even in my professional life, I’m sure I’ve written code that caused someone maintaining it later to yell ‘WTF’. Never Vector Oriented Programming, but I have been accused of using HashMap Oriented Programming.

Apart from mistakes anyone beginning could make, there are also folks (we’ve all met them) who just shouldn’t be coding. That’s where this site truly shines: gobs of examples. The Brillant Paula is one great one, among others.

This site is humbling and astonishing. It reminds me of the old chestnut: if your computer was a car; software ‘engineering’ has a long way to go before it truly becomes engineering.