The RHQ project is building a new user interface using GWT (actually, SmartGWT). There is a definite learning curve to SmartGWT but overall I think this is a great technology for UI building. It offers a rich set of GUI Widgets, a strong architecture, an active community, and responsive developers. But maybe best of all, since you can write your GUI in Java, it can quickly enable a historically non-GUI Java programmer (like me) to contribute to a GUI implementation. As we move forward I'll try and share some tips about things we've stumbled over.
Tip: Remember that hosted mode (i.e. dev mode) is driven by Java, but your standard runtime environment is JavaScript.
GWT takes your Java code and generates vendor-specific JavaScript. This is great in that it frees the Java developer from having to, for the most part, deal with JavaScript or certain vendor-specific browser differences. But, during development you'll be running in hosted mode in order to run with a JPDA debugger, and to evaluate code changes quickly. As you learn quickly in GWT, not everything in Java is available in GWT, because it needs to be able to be supported in the resulting JavaScript. But even the things that are supported may not behave exactly the same way. One example is regular expression (regex) evaluation.
In most cases the evaluation will be the same. But, you may want to test patterns you're using in both a Java regex evaluator and a JavaScript regex evaluator, ensuring they behave the same way.
I ran into this sort of regex problem recently. Here is a slightly contrived example:
(foo|foo/bar)/[^/]*
I wanted to match path segments like: foo/1234 or foo/bar/1234
In Java (i.e when running in dev mode for GWT) this worked just fine, both of the sample paths matched just fine.
The match went like this:
"foo/1234"
(foo|foo/bar) matched "foo"
/[^/]* matched "/1234"
"foo/bar/1234"
(foo|foo/bar) matched "foo/bar"
/[^/]* matched "/1234"
But in JavaScript the second example did not work as I expected.
"foo/1234"
(foo|foo/bar) matched "foo"
/[^/]* matched "/1234"
"foo/bar/1234"
(foo|foo/bar) matched "foo"
/[^/]* failed "/bar/1234"
After matching the first OR option, it did not try the second one, despite the fact that the overall match failed.
The solution was to order the OR options from most complex to least complex, avoiding the subtle issue created by option 1 being a substring of option 2:
(foo/bar|foo)/[^/]*
The left to right evaluation now gave us the desired result.
This is not a blog about regex handling, there are probably several ways to do what we wanted, and we're not encountering a bug here. This is to point out a fundamental design point in GWT development, keep in mind that dev mode and production mode have different runtime environments that can produce subtle differences in behavior. For the same reason you're sure to encounter entire Java classes that work in dev mode and are not available in production mode, because they aren't supported in the JavaScript environment.
Friday, February 18, 2011
Subscribe to:
Posts (Atom)