Tag Archives: JavaScript

Jiffy – The JavaScript File Editor

Jiffy - JavaScript File Editor

You’ve got flat files?  That’s understandable.

In the beginning was the flat file: that simple but effective means of data interchange. Long before there were web services, systems shared data through files having custom record and field layouts.

Yet these things are alive, well, and growing today; for example, nearly all payments travel in some sort of standard flat file format. And since “the wonderful thing about standards is that there are so many to choose from,” hundreds of proprietary file formats support these industry-standard ones.

So, not surprisingly, I’ve found myself over time building custom viewers and editors for various file formats that we use. These are mostly fat-client Windows apps that must be installed to use. I promised myself that the next time I needed a new custom flat file viewer/editor, I would create it as a single-page app.

That time has come, and since I’ve been working with AngularJS and Bootstrap, I decided to use that stack. Hence, Jiffy – the JavaScript File Editor. It’s simple but easily extended: it can support a new file format just by adding a JSON file definition for it. It keeps everything local (in the browser) so no private data is ever sent to a server.

The initial version is now on GitHub, npm, and bower. If you’re also surrounded by flat files, give Jiffy a try. And if you create custom file definitions that others might like, please send me a pull request to add it to the collection.

JavaScript Tools

bracketsOne of my current projects is a single-page responsive app with several JavaScript / HTML5 frameworks: AngularJS, Bootstrap, jQuery, Underscore, RequireJS, etc. These are awesome, but my usual server-side editors (Eclipse, IntelliJ, Vim) are not a great fit.

Perhaps not surprisingly, many new web-dev editors are built in JavaScript. Here are two that I now use regularly and highly recommend:

  • Brackets.io. This open-source editor is still being cooked by Adobe, but it’s already awesome. It’s fast and featured, with some good extensions like Vim bindings.
  • Draw.io. Yes, Visio is terrible and getting worse, as are many “enterprise architect” drawing tools. Meanwhile, the web-based draw.io is free, lightweight, easy to use, and often exactly what you need.

Perhaps if it ends with “io,” it must be good.

jQuery Mobile

This week, I needed a quick mobile (smart phone) proof-of-concept for one of our web app products.  Since speed of development and broad platform support were more important than native device features, I took the mobile web route.  And as a jQuery fan, I chose jQuery Mobile (JQM).

JQM emphasizes doing as much as possible with simple HTML5 and CSS.  It uses data-* custom attributes to know how to add extra behaviors, rendered and tailored as needed for the target device.  Indeed, I found I could do most things with just markup and server-side code, and very little additional JavaScript.

JQM makes AJAX calls by default, but normally expects the results to be new page divs to add to the navigation stack.  This is different from my standard web app, where $.ajax calls return only data (XML and JSON), with bits of JavaScript to update DOM components from the results.  I decided to play along and add div wrappers around results, letting JQM navigate to them as simple linked pages (href=, action=) and dialogs (data-rel=”dialog”).  The end result was cleaner code (and smoother flow than standard postbacks would be), although I did give up a bit in look and feel.

Native app development requires real devices or emulators (such as the Android Virtual Device, AVD), but with a pure mobile web app, I was able to just use Chrome with the nice Ripple extension.  This removed all delays from the code-run cycle: yet another benefit of the mobile web / HTML5 world.

I went with a standard theme and did not (yet) need the extra step of packaging for offline use or adding a native wrapper (like PhoneGap/Cordova).  But those processes appear straightforward when the time comes.  The were a few little glitches along the way, but nothing I couldn’t work around with a little JavaScript.

jQuery Mobile is perhaps the go-to framework for HTML5 mobile web apps.  Certainly for those of us who are sold on the benefits of jQuery.

Friday Fixes

It’s Friday, and time again for some Friday Fixes: selected problems I encountered during the week and their solutions.

Today’s post will be the last of the Friday Fixes series.  I’ve received some great feedback on Friday Fixes content, but they’re a bit of a mixed bag and therefore often too much at once. So we’ll return to our irregularly unscheduled posts, with problems and solutions by topic, as they arrive.  Or, as I get time to blog about them.  Whichever comes last.

More Servlet Filtering

On prior Fridays, I described the hows and whys of tucking away security protections into a servlet filter. By protecting against XSS, CSRF, and similar threats at this lowest level, you ensure nothing gets through while shielding your core application from this burden.  Based on feedback, I thought I’d share a couple more servlet filter security tricks I’ve coded.  If either detects trouble, you can redirect to an error page with an appropriate message, and even kill the session if you want more punishment.

Validate IP Address (Stolen session protection)

At login, grab the remote IP address: session.setAttribute(“REMOTE_IP_ADDR”, request.getRemoteAddr()). Then, in the servlet filter, check against it for each request, like so:

private boolean isStolenSession(HttpServletRequest request) {    
    String uri = request.getRequestURI();
    if (isProtectedURI(uri)) {
        HttpSession session = request.getSession(false);
        String requestIpAddress = request.getRemoteAddr();            
        if (session != null && requestIpAddress != null) {
            String sessionIpAddress = (String) session.getAttribute("REMOTE_IP_ADDR");
            if (sessionIpAddress != null)
                return !requestIpAddress.equals(sessionIpAddress);
        }
    }
    return false;
}

Reject Unsupported Browsers

There may be certain browsers you want to ban entirely, for security or other reasons.  IE 6 (“MSIE 6”) immediately comes to mind.  Here’s a quick test you can use to stop unsupported browsers cold.

private boolean isUnsupportedBrowser(HttpServletRequest request) {
    String uri = request.getRequestURI();
    if (isProtectedURI(uri)) {
        String userAgent = request.getHeader("User-Agent");
        for (String id : this.unsupportedBrowserIds) {
            if (userAgent.contains(id)) {
                return true;
            }
        }
    }
    return false;
}

Community Pools

In my last Friday Fixes post, I described how to use Apache DBCP to tackle DisconnectException timeouts.  But as I mentioned then, if your servlet container is a recent version, it will likely provide its own database connection pools, and you can do without DBCP.

When switching from DBCP (with validationQuery on) to a built-in pool, you’ll want to enable connection validation.  It’s turned off by default and the configuration settings are tucked away, so here’s a quick guide:

Servlet Container Configuration Steps
Tomcat 7 (jdbc-pool) Add the following to Tomcat’s conf/server.xml, in the Resource section containing your jdbc JNDI entry:

  • factory=”org.apache.tomcat.jdbc.pool.DataSourceFactory”
  • testOnBorrow=”true”
  • validationQuery=”select 1 from sysibm.sysdummy1″
WebSphere Set the following in Admin Console:

Resources – JDBC – Data sources > (select data source) > WebSphere Application Server data source properties:

  • Check “Validate new connections”, set “Number of retries” to 5 and set “Retry interval” to 3.
  • Check “Validate existing pooled connections”, and set “Retry interval” to 3.
  • Set “Validation options – Query” to “select 1 from sysibm.sysdummy1”.
WebLogic Set the following in the Administration Console:

JDBC – Data Sources – (select data source) – Connection Pool – Advanced:

  • Check “Test Connections on Reserve”
  • Set “Test Table Name” to “SQL SELECT 1 FROM SYSIBM.SYSDUMMY1”
  • Set “Seconds to Trust an Idle Pool Connection” to 300.

Adjust intervals as needed for your environment.  Also, these validation SQLs are for DB2; use equivalent SQLs for other databases.

Auto Logoff

JavaScript-based auto-logoff timers are a good complement to server-side session limits.  Such are especially nice when coupled with periodic keep-alive messages while the user is still working.  The basic techniques for doing this are now classic, but new styles show up almost daily.  I happen to like Mint‘s approach of adding a red banner and seconds countdown one minute before logging off.

Fortunately, Eric Hynds created a nice jQuery-based Mint-like timer that we non-Intuit folks can use.  It uses Paul Irish’s idleTimer underneath.

Dropping it in is easy; just include the two JS files and add the idletimeout div into your common layout.  I tucked the boilerplate JavaScript into a simple common JSPF, like so:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<script src="<c:url value="/script/jquery.idletimer.js"/>"></script>
<script src="<c:url value="/script/jquery.idletimeout.js"/>"></script>
<script>
var idleTimeout = <%= SettingsBean.getIdleTimeout() %>;
if (idleTimeout > 0) {
  $.idleTimeout('#idletimeout', '#idletimeout a', {
	idleAfter: idleTimeout,
	pollingInterval: 30,
	keepAliveURL: '<c:url value="/keepalive" />',
	serverResponseEquals: 'OK',
	onTimeout: function(){
		$(this).slideUp();
		allowUnload();
		window.location = '<c:url value="/logout" />';
	},
	onIdle: function(){
		$(this).slideDown(); // show the warning bar
	},
	onCountdown: function( counter ){
		$(this).find("span").html( counter ); // update the counter
	},
	onResume: function(){
		$(this).slideUp(); // hide the warning bar
	}
  });
}

Inanimate IE

Among Internet Explorer’s quirks is that certain page actions (clicking a button, submitting, etc.) will freeze animated GIFs.  Fortunately, gratuitous live GIFs went out with grunge bands, but they are handy for the occasional “loading” image.

I found myself having to work around this IE death today to keep my spinner moving.  The fix is simple: just set the HTML to the image again, like so:

document.form.submit();
// IE stops GIF animation after submit, so set the image again:
$("#loading").html(
 '<img src="<c:url value="/images/loading.gif"/>" border=0 alt="Loading..." />');

IE will then wake up and remember it has a GIF to attend to.

Dissipation

The trouble with keeping your data in the cloud is that clouds can dissipate.  Such was the case this week with the Nike+ API.

Nike finally unveiled the long-awaited replacement for their fragile Flash-based Nike+ site, but at the same time broke the public API that many of us depend on.  As a result, I had to turn off my Nike+ Stats code and sidebar widget from this blog.  Sites that depend on Nike+ data (dailymileEagerFeet, Nike+PHP, etc.) are also left in a holding pattern.  At this point, it’s not even clear if Nike will let us access our own data; hopefully they won’t attempt a Runner+-like shakedown.

This type of thing is all too common lately, and the broader lesson here is that this cloud world we’re rushing into can cause some big data access and ownership problems.  If and when Nike lets me access my own data, I’ll reinstate my Nike+ stats (either directly, or through a plugin like dailymile’s).  Until then, I’ll be watching for a break in the clouds.

Broken Tiles

I encountered intermittent problems where Apache Tiles 2.2.2 where concurrency issues cause it to throw a NoSuchDefinitionException and render a blank page.  There have been various JIRAs with fixes, but these are in the not-yet-released version 2.2.3.  To get these fixes, update your Maven pom.xml, specify the  2.2.3-SNAPSHOT version for all Tiles components, and add the Apache snapshot repository:

<repository>
    <id>apache.snapshots</id>
    <name>Apache Maven Snapshot Repository</name>
    <url>http://repository.apache.org/snapshots</url>
</repository

Hopefully 2.2.3 will be released soon.

Toolbox Linkapalooza

A few favorite tools I used this week:

  • WebScarab – Nice Ethical Hacking tool.  Among many features, it exposes hidden form fields for editing.
  • Burp Suite – Similar to WebScarab; its proxy and intruder features make packet capture, modification, and replay a snap.
  • Runner’s World Shoe Advisor.

Friday Fixes

It’s Friday, and time again for some Friday Fixes: selected problems I encountered during the week and their solutions.

I got a friendly reminder this morning that I’ve neglected my Friday Fixes postings of late.  I didn’t say they’d be every Friday, did I?  At any rate, here are some things that came up this week.

Tabbed Freedom v. Logoff Security

Tabbed browsing is a wonderful thing, but its features can become security concerns to corp-rat folks who mainly use their browsers for mission critical apps.  For example, with most browsers, closing a tab (but not the browser itself) does not clean up session cookies. Yet those security first guys would like to have a way to trigger a log off (kill the session) on tab close.

This is a common request, but there’s no straightforward solution. As much as I’d like browsers to have a “tab closed” event, there isn’t one.  The best we can do is hook the unload event which is fired, yes, when the tab is closed, but also anytime you leave the page: whether it’s navigating a link, submitting a form, or simply refreshing.  So the trick is to detect and allow acceptable unloads.  Following is some JavaScript I pieced together (into a common JSPF) based loosely on various recommendations on the web.

  var isOkToUnload = false;
  var logoffOnClose = '<c:out value="${settingsBean.logoffOnClose}" />';
 
  function allowUnload() {
     isOkToUnload = true;
  }
  function monitorClose() {
     window.onbeforeunload = function() {
        if (!isOkToUnload)
           return "If you leave this page, you will be logged off.";
     }
     window.onunload = function() {
        if (!isOkToUnload) {
           $.ajax({
              async: false, type: "POST",
                   url: '<c:url value="/basiclogout"/>' });
        }
     }   
     // Add other events here as needed
     $("a").click(allowUnload);      
     $("input[type=button]").click(allowUnload);      
     $("form").submit(allowUnload);                     
  }
 
  $(document).ready(function() {
     if (logoffOnClose === 'Y')
        monitorClose();
  });

This triggers on refresh, but that’s often a good thing since the user could lose work; Gmail and Google Docs do the same thing when you’re editing a draft.  It’s a good idea to make this behavior configurable, since many folks prefer the freedom of tabbed browsing over the security of forcing logoff.

DBCP Has Timed Out

Right after mastering the linked list, it seems every programmer wants to build a database connection pool.  I’ve built a couple myself, but this proliferation gets in the way of having a single golden solution that folks could rally around and expect to be supported forever.

Such was the story behind Apache DBCP: it was created to unify JDBC connection pools.  Although it’s broadly used, it’s over-engineered, messy, and limited. So it, too, fell by the wayside of open source neglect.  And since nearly all servlet containers now provide built-in connection pools, there’s really no use for DBCP anymore.

Yet I found myself having to fix DisconnectException timeouts with an existing DBCP implementation, typically stemming from errors like:  A communication error has been detected… Location where the error was detected: Reply.fill().

After trying several recovery options, I found that DBCP’s validationQuery prevented these, at the cost of a little extra overhead.  Although validationQuery can be configured, I didn’t want additional setup steps that varied by server.  So I just added it to the code:

  BasicDataSource ds = new BasicDataSource();
  // ...
  ds.setValidationQuery("select 1 from sysibm.sysdummy1");
  ds.setTestOnBorrow(true)

In the next pass, I’ll yank out DBCP altogether and configure pools in WebSphere, WebLogic, and Tomcat 7.  But this gave me a quick fix to keep going on the same platform.

Aggregation Dictation

Weird: I got three questions about aggregating in SQL on the same day.  Two of them involved OLAP syntax that’s somewhat obscure, but quite useful.  So if you find yourself with complications from aggregation aggravation, try one of these:

  • Doing a group by and need rollup totals across multiple groups?  Try grouping sets, rollup, and cube.  I’ve written about these before; for example, see this post.
  • Need to limit the size of a result set and assign rankings to the results?  Fetch first X rows only works fine for the former, but not the latter.  So try the ranking and windowing functions, such as row_number, rank, dense_rank, and partition by.  For example, to find the three most senior employees in each department (allowing for ties), do this:

      SELECT * FROM
       (SELECT rank() OVER(partition BY workdept ORDER BY hiredate ASC) 
        AS rank, firstnme, lastname, workdept, hiredate 
        FROM emp) emps
      WHERE rank <= 3
      ORDER BY workdept

    Co-worker Wayne did a clever row_number/partition by implementation and added a nice view to clarify its meaning.

Linkapalooza

Some interesting links that surfaced (or resurfaced) this week:

Friday Fixes

It’s Friday, and time again for some Friday Fixes: selected problems I encountered during the week and their solutions.

CSS – Space Matters

Guess you could say I was “lost in [a] space” wondering why my browser didn’t pick up my div’s CSS class.  Turns out, I wrote the selector as #myid .myclass (descendent selector) but really meant #myid.myclass (combined selector). Thank you, 2.5x reading glasses and Chris Coyier, for the quick save.

Point of No Return

JavaScript and jQuery iterator functions are awfully convenient, but it’s easy to overlook scope.  While refactoring some code today, I wrapped a function around some iterator code for reuse and broke it. Here’s a simplified example to demonstrate the problem:

     function myFunction() {
        $.each(['a', 'b', 'c'], function(idx, ea) {
           if (ea === 'b') {
              return ea;
           }
        });
     }

At a glance, you’d think myFunction returns b, but since the inner function’s result is never passed out, it returns undefined.  And jQuery’s each method just returns the collection, so adding a return in front doesn’t help.  jQuery does have some alternatives (like filter) that can help, but those aren’t as flexible as each.

The simple solution is to just carry the value to the outer scope, like so:

     function myFunction() {
        var result;
        $.each(['a', 'b', 'c'], function(idx, ea) {
           if (ea === 'b') {
              result = ea;
              return false;
           }
        });
        return result;
     }

Adding the “return false” stops the iteration at the first match.

Is this Thing Used?

My current project has this DB2 LUW fan coding against a DB2 for z/OS database.  While I give up a some things, I also gain a lot.  For example, while working on a DAO, I had questions about a particular table’s indexes.  Fortunately, DB2 for z/OS has SYSINDEXPLANSTATS which, among other things, keeps track of the last time an index was used (even for dynamic SQL) to help determine its merits.  So I first checked to see if this was at least version 9:

select getvariable('SYSIBM.VERSION') from sysibm.sysdummy1;

… and then answered my questions with a simple query like the following:

select i.name, i.tbname, i.creator, i.uniquerule, i.colcount, i.clustering, s.lastused
from sysibm.sysindexes i, sysibm.sysindexspacestats s
where i.name = s.name
and i.creator = s.creator
and i.dbname = 'MYDB'
and i.tbname like 'MYPREF%'
order by s.lastused

Can’t wait for this to make its way to DB2 LUW.

VSSibility

Yes, I presently have to use Microsoft Visual SourceSafe (VSS).  I’m over it now.  When using this “lock first” VCS against a deep project hierarchy, I often need to see a quick list of my check-outs.  I can use View->Search->Status Search (with subprojects selected) from the VSS GUI, but that’s often too slow over a remote VPN connection.  So I cooked up a quick script to run over an ssh command line from a server that is “local” to the repository:

cd /d "C:\Program Files\Microsoft Visual SourceSafe"
set SSDIR=\\myserver\VSS\myvssshare
ss STATUS $/MyProject -R -Umyusername

Flexigrid Echo

Imitation isn’t always flattering; it’s often annoying.  Having two Flexigrids on one page, both with pagers enabled (usepager: true) yielded some weird mocking behavior.  For example, paging forward on one grid caused both grids to show the same “Page X of Y” message.  After debugging, I found that similar bugs had been reported and fixed in the latest release.  Upgrading Flexigrid resolved that one.

Friday Fixes

Friday Fragments served a useful purpose, one of which was regularity: funny how Fridays kept coming around.  While I haven’t been in pedagogical fragment mode for awhile, I encounter real life puzzles every day.  Sharing these often helps others who encounter the same problems, or even myself when I need a quick reference down the road.  I just need a reminder and motivator to stop and record these.  I suppose Friday is as good as any.

So here goes the first installment of Friday Fixes: selected problems I encountered during the week and their solutions, along with other sundries.

Spring Loading

Like most form tags, binding a multi-select list in Spring MVC is easy: deceptively so.  All you need is this, right?

<form:select path="myFavorites" id="myFavorites" size="3" multiple="true" class="myList">
	<form:options items="${allChoices}" />
</form:select>

And, of course, the model attribute and/or bean methods to return the allChoices collection and get/set myFavorites.  Well, not so fast.  Turns out, multi-select lists in Spring MVC have always been a bit of a pain, particularly when it comes to making the initial selections (convincing Spring to add the selected attributes) on initial page load.  One pre-selection is fine, but with multiples, the comma-separated list pushed back into the model’s setter is a one-way trip.

Solving this in prior versions of Spring required using an InitBinder whether you otherwise needed one or not.  But for Spring MVC 3, the fix is to just map to collection getter/setters, even if your model wants to use the comma separated list.  For example, use the following getter and change the form:select path to use it: path=”myFavoritesList.

	public List getMyFavoritesList() {
		List list = new ArrayList();
		for (String fav : getMyFavorites().split(",")) {
			list.add(fav);
		}
		return list;
	}

Time(outs) May Change Me…

Between the deadlock event monitor, db2pd, and snapshots, DB2 has long provided good tools for tracking down deadlock culprits.  But for lock timeouts, not so much.  The DB2 folks have tried to improve things lately, but they’ve changed their minds a lot, often adding new tools and then quickly taking them away.

Now that lock timeout event monitors are finally here, many of the other new approaches like db2_capture_locktimeout and db2pdcfg -catch (with db2cos call-out scripts) have been deprecated.  A coworker was concerned about the passing of db2_capture_locktimeout, but it appears it’ll be around a little longer.  For example, the following still works in even the latest 9.7 fixpacks.

db2set db2_capture_locktimeout=on
db2stop & db2start
db2 get db cfg for sample show detail | find /i "timeout"
db2 update db cfg for sample using locktimeout 30
db2 connect to sample
db2 -c- update org set deptname=deptname

Repeat the last two commands in another DB2 Window and then wait for the timeout.  Look for the report under your DIAGPATH, SQLLIB, or Application Data folder; for example: dir db2locktimeout*.* /s.  Even with the latest 9.7 fixpacks, the timeout report can occasionally have some holes in it (like missing SQLs), but it’s still quite useful.

Flexigrid Incantation

Got a Flexigrid with a radio button?  Want to fetch the value of a column on the radio-selected row?  Well, when Flexigrid generates the tds and divs from your colModel, it provides abbr attributes, not ids.  So the usual jQuery shorthands to find by ID don’t apply, and you’re off chasing the more obscure abbr.  For example:

$('.mytable').find('tr').each(function (index, tr) {
	if($(tr).find('input#sequence').attr('checked')) {
		myvalue = $(tr).find('div#myname').val();          // Nope, doesn't work
		myvalue = $('td[abbr="myname"] >div', tr).html();  // Gotta use this
	}
});

New Toys

My own little Linkapalooza of online tools I found this week and actually used:

Keeping Baby and Bathwater

After untangling some weirdness this afternoon, I feel like joining the masses storming the JavaScript Bastille.  But it’s too late for that with this “can’t live with it, can’t live without it” language.

A Big Baby

JavaScript is unmatched for its immaturity and ubiquity.  Both, of course, are intertwined.  With an installed base of a few billion JavaScript-enabled browsers out there, it’s virtually impossible to break compatibility and significantly fix this underdeveloped language.  The slow progress of the ECMAScript committee doesn’t help matters.  Hence so many “compile to JavaScript” tools and languages: GWT, CoffeeScript, Dart, etc.  But if going non-native were truly a good idea, we’d all be debugging bytecode.

As the size of our JavaScript code bases continues to explode (propagated by richer clients and SSJS), maybe we finally accept that the raw, unevolved language is here to stay and, since we can’t fix it, do a better job of propping it up.  Since many (perhaps most) JavaScript developers don’t naturally write clean code nor stick to The Good Parts on their own, we need code checkers.  Yes, I mean lint, but one that folks will actually use.

JSLint – A Good Start

If a proliferation of cross-compilers condemns a language, the proliferation of lint tools condemns its compilers, editors, and IDEs.  Lint tools typically fill the gap where a language lacks or the tools haven’t caught up or caught on.  Few people still use a separate C lint because most compilers and IDEs have integrated their most important checks.  And PMD became less important to me as I started tweaking Eclipse’s Java compiler warnings (although it still needs better file and package filtering).

There are a few JavaScript lint options; I prefer Douglas Crawford’s own JSLint and its recent JSHint fork.  It can be a bit pedantic, overemphasizing style.  Some of the trivial style checks can be disabled (for example, white: true and vars: true), while others can’t (“Mixed spaces and tabs”, really??).  But it’s helpful enough at catching things to be worth using in spite of its false alarms and awkwardness.

But what JSLint lacks most is integration: both with embedded source and standard tools.  That is, JavaScript source is often in server-side pages like JSPs, intermixed with form tags, embedded foreign language, and other noise that JSLint can’t handle.  The work-around is to let the server render it and then paste it into JSLint, but couldn’t someone integrate JSP parsing smarts with JavaScript validation?  And could we focus energies on making it an extension of Eclipse’s JavaScript validation: one that’s actually useful?

Perhaps smarter code analysis in this loose language is a hard nut to crack.

The Next Level

And that certainly makes sense: static analysis of JavaScript is hard because it isn’t just a dynamic language, it’s the wild west.  Is x a variable, function, property, or value?   Is it local, global, or forgotten?  Without true scoping, access control, and other aids, context is very hard to discern.  JSLint helps by not letting you get away with ambiguity, but arbitrary belts and suspenders aren’t the best solution.  Since we humans often have to let the JavaScript page render and step through it in Firebug to see what’s really going on, can we really expect a computer to figure it out from flat source code?

I think so.  With enough (warranted) attention, JavaScript validation will improve, and we’ll even see better code assist and refactoring tools.  It may take some new ways of looking at the problem, but fortunately, there’s some promising new research happening now.

Looks like we’re stuck with this JavaScript baby and all its dirty bathwater.  But here’s hoping future tooling makes cleaning it up a lot easier.

Node.js

A lingering sense of abandonment dating back to Netscape’s LiveWire leaves me leery of server-side JavaScript (SSJS).  Not that it’s a bad idea, it just didn’t gain traction.  JavaScript as a language is great but, by design, it lacks built-in I/O support and other things required for writing servers.  And with no standard platform to fill these holes, JavaScript remained relegated to sandboxes, mainly browers and system extensions.

That’s all been changing as SSJS proponents have rallied around Node.js, a toolkit for easily building scalable event-driven servers running atop Google’s V8 JavaScript Engine.  It was easy to ignore Node’s initial hype, but when I found myself needing to serve up some new REST APIs, I thought I’d check it out.  Besides, my AJAX calls can point anywhere, so there was really no risk in trying.  If it didn’t work out, I could always abandon Node and fall back to something more conventional, maybe even EventMachine.

Getting started was quick and easy.  Cloning and building takes only a few minutes; even faster, binaries are just a sudo apt-get install away.  There are many online tutorials, so I worked through the obligatory web server and other examples.  There’s not a lot going on in my services, so I couldn’t factor them into many event-driven/parallel fragments.  But I quickly got a feel for doing things the Node way: spinning off handlers, writing callbacks, and even running multiple node processes.  With help from Node’s non-blocking libraries, that single-threaded event loop wasn’t a bottleneck.

It didn’t take long to complete my work, so I quickly got to the question of deployment.  Sure, I have VMs out there where I can run whatever I want, but I needed this running under my jailed hosting service.  The awesome Heroku service now supports Node, but I stopped short of rolling it out there.  So I’m keeping it local now as I build out the other pieces.

Node has come a long way fast and appears to have a bright future.  It has a rich and growing ecosystem of basic modules and frameworks for web apps/MVC, content management, blogs, comet, etc.  Time will tell how pervasive Node becomes, but for shops wanting JavaScript all the way down, it’s a very nice platform choice.

GWeaT New Release

I no longer actively use Google Web Toolkit (GWT), but some affinity remains.  I don’t miss experiencing its growing pains from 1.3 to 1.6: maintaining parallel hierarchies of cross-compilable business and transfer objects, forging and tweaking copy and mutation frameworks, debugging generated JavaScript, deployment issues, waiting seemingly forever for Java 5 and 6 support, and so on.  But spending trench time in any new technology has a way of fostering interest in seeing it mature.

And mature it has!

After a long stream of GWT updates with relatively small incremental enhancements, GWT 2.0 is a major leap forward, and a game changer.  It’s the GWT I’ve always wanted, and one I wish I had at the beginning.

Google has finally taken on the tools side of the equation with their own Eclipse plug-in.  Its operation is smooth and seamless: no more cobbled-up mash of third-party plugins, Cypal studio, and gwtCompile Ant tasks.

I’m thrilled to see the death of hosted mode; Google now offers native browser plug-ins for debugging.  I used the plug-ins for Firefox (3.5.7) and Chrome (4.0.302.3, dev channel) and debugging was a breeze, albeit sluggish at times.  Among other things, this ends the problem of code working one way in hosted mode and another way (or not at all) when deployed to a browser.

The Speed Tracer looks promising for performance monitoring and tuning.  However, I could not get past its “no data received in 6 seconds” error.  I used the latest dev channel version of Chrome and followed instructions carefully (including the command line switch), but must have missed something.  I’ll give this a closer look along with the many other features later.