Friday, January 20, 2012

JavaScript and Scala: Good Parts and Bad

I've just finished reading "JavaScript: The Good Parts" by Douglas Crockford. It's a fantastic book, mostly because it's incredibly concise, elaborating only the details that experienced programmers should need to understand the true form of JavaScript. If you do ANY JavaScript programming and you haven't read it, I suggest you go out and get it straight away, and don't write a single line more of buggy JS code until you do.

What is 'this'?
Early on in the book, Crockford highlights one of JavaScript's oddest and most dangerous quirks: the late binding of 'this'. Basically, whenever you call a function, the value of 'this' within the function is determined by HOW you called the function!

To demonstrate: If object 'a' has a function called 'run()' and you invoke it like this:
a.run();
then the value of 'this' within 'run()' will be 'a'. JavaScript is a functional language, so functions can be passed around as values. If you instead invoked the function above using only a reference to the function value, like this:
var f = a.run;
f();
then the value of 'this' within 'run()' will be... the global variable pool! As you can imagine, that can lead to some pretty nasty and hard to track bugs.

Functional Limitations
 If you're a fan of functional programming, you might have tweaked straight away that this could place limits on the usefulness of functions as first class objects, and specifically higher-order functions (i.e. functions that take other functions in their parameters).

Here's an example of an object that doesn't work with higher-order functions:
var object1 = {
    total: 0,
    add: function(numbers) {
        var i;
        for (i = 0; i < numbers.length; i++) {
            this.total += numbers[i]
        }
        return this.total;
    }
};

var valueOf = function (f, p1) {
    return f(p1);
}

var numbers = [1, 2, 3, 4];

document.writeln(object1.add(numbers) + " / " + valueOf(object1.add, numbers));
// outputs: 10 / NaN
Obviously the reason this quirk causes confusion is because JavaScript has borrowed a keyword from other languages but uses it to mean something subtly different. Most OO languages use 'this' to represent a pointer to an object in which the function seemingly resides. Importantly, in OO/functional languages, when a function is used as a value, it takes with it a closure around 'this' that is used when invoking it. In JavaScript, however, the 'this' pointer just refers to the object on which the function was called, or if there was no object, just to the global variable pool.

This Naughtiness Explained
There is a reason for this weirdness. Because JavaScript is classless, the function doesn't actually belong to the object in which it resides. In fact, it's not hard to imagine situations where JavaScript's behaviour is what you'd expect. If I took a function from one object and placed it in another object (which I can do, because the function is also a value), I actually would expect 'this' to refer to the new object when I invoked it, and JavaScript provides just that capability:
var b = {};
b.run = a.run;
b.run(); // 'this' will refer to 'b'
Once you understand where JavaScript is coming from a bit better, it's not too hard to see the solution to this problem. 'this' doesn't provide a closure around the context where your function was defined, so if you want a closure around the context where your function was defined, then give your function a closure around that context, rather than assuming that 'this' will be the same context whenever the function is invoked. To demonstrate this by correcting the example above:
var object2 = (function () {
    var that = {};
    that.total =  0;
    that.add = function(numbers) {
        var i;
        for (i = 0; i < numbers.length; i++) {
            that.total += numbers[i]
        }
        return that.total;
    };
    return that;
})();

document.writeln(object2.add(numbers) + " / " + valueOf(object2.add, numbers));
// outputs: 10 / 20
Scala: The Bad Parts?
 Does any of this have anything to do with Scala? Well, in the details, no, but in the general sense there is a very important approach in Crockford's book. His suggested solution to the problem above is simple: don't use 'this' in JavaScript and don't use its accompanying feature, 'new'. In fact, he suggests not using LOTS of features of JavaScript. He dedicates 14 pages of appendix to listing them.

Crockford also spends a very un-indulgent two pages discussing the modern phenomenon of "feature-driven design", both in products and programming languages, explaining how "Features that offer value to a minority of users impose a cost on all users" and concluding the book with this pearler: "It would be nice if products and programming languages were designed to have only good parts."
It was those two lines that caused me to reflect on Scala. I started asking myself questions like: Are there too many features in Scala? Are there parts that aren't "good parts"? Are there features that very few people make use of but that cost everyone because of the complexity they add? From my own experience, the answer to all three of these is "yes".

Crockford explains that we all crave simplicity and that, when we aren't given it, we make it for ourselves by creating our own feature subset, and I realised that I've done this to some extent in the way I use Scala. So finally I began wondering how long it will be until someone publishes "Scala: The Good Parts", complete with appendices listing all the features that you should steer clear of for everyone's sake. What confusing or dangerous feature of Scala do you reckon will be at the top of the list?

Want to learn more?

From Amazon...

From Book Depository...

Sunday, January 8, 2012

Updates to Scala/Spring/Hibernate/Maven Webapp

One of the projects I maintain is a public domain code base on GitHub called Scala-Spring-Hibernate-Maven-Webapp. The repository contains source code for kickstarting your own webapp project using the latest versions of Scala, Spring Web, Hibernate and Maven.

Project Updates
I've been committing some major changes over the last couple of weeks, including:
  • Upgrading to Scala 2.9.1, Spring 3.1.0 and Hibernate 4.0.0 
  • Adding to the existing REST-ful Create and Retrive examples some Update and Delete operations 
  • Adding server-side form validation using JSR-303 annotations with Spring Web MVC 
  • Creating examples of automated web testing using Selenium WebDriver and the PageObjects pattern
 If you're about to start your own project with these technologies, or are just keen to see how they all work together, you can get your own copy of the source code from here:
https://github.com/GrahamLea/scala-spring-hibernate-maven-webapp

Resolved Issues
I encountered a couple of time-consuming issues during the upgrades to the latest versions and I think it would be worth sharing how they were resolved in order to save some time for others googling for solutions to the same problems.

Spring Schema SAXParseException
After upgrading the versions of all the Spring Schemas in my Spring XML files, I started getting the following error while trying to start up the webapp:
org.xml.sax.SAXParseException: cos-all-limited.1.2: An ''all'' model group must appear in a particle with '{'min occurs'}'='{'max occurs'}'=1, and that particle must be part of a pair which constitutes the '{'content type'}' of a complex type definition.
At first this appears to be a bug in the Spring schema, but a bit more investigation revealed that it is, in fact, a bug in an old version of the Xerces XML parser library. In my case, an old version of the library was being pulled in through commons-dbcp. The solution I took was to explicitly add a dependency on the latest version of Xerces:
        <dependency>
            <groupId>xerces</groupId>
            <artifactId>xercesImpl</artifactId>
            <version>2.9.1</version>
            <scope>runtime</scope>
        </dependency>

Hibernate Function Not Supported
After upgrading Hibernate to 4.0.0, I started getting this error message whenever I tried to execute a query:
org.hibernate.exception.GenericJDBCException: This function is not supported
Caused by: java.sql.SQLException: This function is not supported
I don't remember whether HSQLDB appeared in the stack trace or not, but the solution to this was to upgrade the version of HSQLDB I was using from 1.8.0.10 to 2.2.6. If you get the same error and you're not using HSQLDB, I would suggest considering an upgrade of your JDBC driver or maybe even your database server.

"No Session found for current thread" 
Also after upgrading to Spring 3.1.0 and Hibernate 4.0.0, and after changing all my Hibernate 3 Spring beans to the corresponding Hibernate 4 versions, I started getting the old classic "No Session found for current thread" error when trying to view any page with a transaction. I thought this was very odd, because the traditional solution to this has always been to make sure you have an OpenSessionInViewInterceptor, but I already had one, defined like this:
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="interceptors">
            <list><ref bean="openSessionInViewInterceptor"/></list>
        </property>
    </bean>
By pure chance, I'd seen a Spring documentation page earlier the same day where I'd noticed an alternative way of declaring interceptors using the 'mvc' namespace:
    <mvc:interceptors>
        <ref bean="openSessionInViewInterceptor"/>
    </mvc:interceptors\>
Replacing my old DefaultAnnotationHandlerMapping definition with the one above got my OpenSessionInViewInterceptor working again and solved the "No Session found for current thread".

No Appenders for Log4J
Finally, this one is a bit silly, but I spent a good half hour on it without finding any good help on the web so I thought it was worth documenting. At some point I started getting this error out of Log4J every time I started my webapp:
log4j:WARN No appenders could be found for logger
After all kinds of googling, experiments with winding back dependency upgrades and investigations into ClassLoaders, I eventually noticed that I just had a typo in the Log4J configuration file:
og4j.rootCategory=INFO,Console
Notice the 'l' missing at the start of that line? Ouch. So if you're getting this error message about no appenders and you think your log4j config is all set up properly, check whether the config for your root category is correct before investing too much time in breakpoints inside Log4J classes.

Want to learn more?
Here's some books you might find useful if you plan to go further with Spring, Hibernate, Scala or Maven:
From Amazon








From The Book Depository

Spring in Action - Craig Walls & Ryan Breidenbach (Manning)

Hibernate in Action - Gavin King & Christian Bauer (Manning)

Spring Recipes - Gary Mak (Apress)

Programming in Scala - Martin Odersky, Lex Spoon & Bill Venners (Artima)

Maven - A Developer's Notebook - Vincent Massol & Timothy M. O'Brien (O'Reilly)