Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Tuesday, December 20, 2011

SodaTest 0.2.1 Released


I've just released the second milestone of SodaTest, the spreadsheet-driven integration testing framework.
A significant change with this release is that SodaTest is now available from the Maven Central repository. You should be able to access the latest versions of all SodaTest artefacts from Maven Central right now as org.sodatest : sodatest-* : 0.2.1
As well as a couple of small bug fixes, this release incorporates a number a improvements based on feedback from use of SodaTest in corporate environments. The key enhancments were:
  • Coercions can now be created in Java without any knowledge of Scala
  • Built-in support was added for coercing strings into Java enums
  • An implicit function is available for converting into a Coercion any function with the type: (String) => _
  • A CurrencyAmountCoercion and CurrencyAmountCoercionForJava are now available for coercing a variety of financial value formats into your own custom Currency or Money class
  • Reports no longer report a mismatch due to trailing empty cells in the actual output
  • A bunch of usability fixes such as handling unusual situations, reporting better error messages, correct usage messages, more scaladoc and READMEs.
So, if you've been holding out from using SodaTest wondering if anyone is using it for real, whether it's going to be improved over time, and whether you should even bother trying it out, the answers are yes, yes and yes!
(And in case you're wondering why this release is 0.2.1 and not 0.2, it's because 0.2 got lost in the first, failed attempt to release from Sonatype to Maven Central.)

Thursday, December 8, 2011

Will Typesafe Address Scala Criticisms?

If you've been paying attention to the Scala corner of the web over the last week, you'll no doubt have heard something about Yammer - an enterprise-focussed social network - switching from Scala back to Java.

If you've been on holidays and missed it all, basically what happened was that Coda Hale, the Infrastructure Architect at Yammer, wrote a private email to the Typesafe team giving loads of mostly critical feedback regarding Scala, but the email was subsequently leaked and became the talk of the town, among both Scala supporters, like David Pollak, and critics, such as Stephen Colebourne.


A Painfully Honest Critique

Firstly, let me summarise the main points in Coda's email:

* Yammer have decided to change their "basic infrastructure stack" from Scala to Java.

* The main reason is that Scala has "friction and complexity" that isn't offset by enough productivity gain.

* Some seemingly simple constructs in Scala, e.g. List, actually have very complex interfaces and behaviour that necessitate explaining a lot of concepts to beginners. The belief by some that this complexity can be ignored except by library authors has proven to be false in practice.

* The most vocal members of the Scala online community are generally very academic in their practice and discussion of Scala.

* Existing libraries seem to be being re-written just because people want to practice their use of advanced functional programming concepts, but these re-writes are then being recommended as the library of choice.

* The Yammer team eventually decided the most sensible way to deal with the Scala community was to ignore it.

* Learning Scala properly is important, but doing so is neither quick nor easy.

* Java is not going away, so the choice to use Scala is actually a choice to use Scala and Java, along with the interaction challenges that brings.

* The Yammer team had "endless issues" with SBT, and found themselves writing plugins to replicate Maven functionality.

* Switching to Maven solved most of their problems, but they found it has been marginalised by the Scala community, with poor support and constant encouragement to switch to SBT.

* The backwards-incompatibility of Scala major releases requires library authors to cross-compile,  which has resulted in library re-invention when authors are no longer committed to the project.

* The backwards-incompatibility also causes headaches for developers, which has resulted in many production Scala deployments not being upgraded to 2.9.

* Yammer found idiomatic Scala code performed very poorly. By eliminating for-comprehensions, avoiding Scala's collection library, avoiding closures and marking everything with private[this], they were able to achieve speed ups of 100x in some components.

So that was that. For what it's worth, Coda's email is also quite complimentary of Scala. I think he gives the impression that he likes it and would really like to keep using it, but the realities of making it work in a day-to-day production-deploying team have weighed them down so much that the benefits have been eclipsed.

A Frustratingly Measured Official Response

Not long after Coda's email became public, Typesafe published on their blog what is quite obviously a public response to the email, and it's that blog I'd like to take a closer look at today.

Here are the main points from the Typesafe blog:

* Typesafe are investing in Scala IDE support by contributing to the Scala IDE for Eclipse

* They are addressing the learning curve by developing training courses, but also provided references to some of the free resources on the web.

* 'scalac' is slow because it has more work to do than 'javac', but they are investigating using parallel and incremental techniques to improve speed, with a focus on improving sbt.

* If you don't want to (or can't) upgrade your Scala version, you can purchase commercial support from Typesafe to get access to long-term maintenance releases of previous versions.

* In order to reduce people's major-release upgrade issues, they are planning to fold a bunch of existing libraries into the Scala release .

* They take performance seriously, but are wary of engaging in premature optimisation.

* Typesafe are not just focused on the Scala language and core libraries but also on frameworks to help build applications more easily.

* They describe the Scala community using a couple of niceties as well as the words "opinionated" and "quirky".

* They say there's many places where Scala could be improved and they're hard at work doing so.

* They mention Yammer amongst a group of other companies with successful production deployments of Scala.



What Aren't They Telling Us?

What I think is most interesting about this response is the things it doesn't mention and the places where it's specific about what they're doing to solve issues.

Firstly, there's no mention of Maven. There is some commitment to improving compile times, but they seem to suggest that this will be for sbt users only. It has to be considered odd that Maven has been given so little attention by the chief proponents of Scala. One of the main advantages often cited for adopting Scala is its easy integration with Java, "so you can continue using all your favourite libraries". But the commitment to prolonging the life of people's Java API knowledge doesn't extend to the Java build chain. Should it? Why is Maven important? It's important because it works, and it's almost ubiquitous. It has had years and years of work poured into it and has been tested and improved by feedback from hundreds of thousands of users and plugin developers. It has a global ecosystem that is well understood. It has become a lingua franca; many people would know how to build their project with Maven but couldn't tell you how to build it with javac and jar. If you want to distribute your project to the world through Maven Central via Sonatype's Nexus repository, they've got fantastically detailed instructions for how to do so... with Maven. The Java-fluent world - which Typesafe want to convert into the Scala world - don't need another build tool. We need relatively minor improvements to Maven and its plugins to ensure we can keeping working without having to learn something completely new.

Secondly, Typesafe give no commitment to eliminating the backwards compatibility problems in future major releases. In fact, one of the parts of their workaround - the offering of paid support for people who want to continue using older releases - actually makes it in their interest to not solve the problem. The other half of their workaround - bringing certain libraries into the Scala release - will mean that, as a developer, your backwards compatibility issues will only be solved if your taste in libraries is similar to those of the Typesafe team. If you like a library that hasn't been deemed worthy of inclusion, you'll be left with all the same cross-compiling and "version-x-for-scala-y" dependency issues that you have now.

Thirdly, they seem to fob off Yammer's performance problems as an issue specific to their environment, suggesting that fixing such things for everybody would be "premature optimisation". I've heard this argument before: that it only makes sense for companies like Yammer and Twitter to spend time optimising tiny bits of code because it can save them millions across all their computers. But the same argument applies to small businesses just as well. If my business is growing rapidly, but I have limited cash flow, having a 100x performance increase is going to make a significant contribution to my bottom line if I can serve all of my customers on one machine instead of 100 machines. "Premature optimisation" is a phrase that should be reserved for application developers, not framework developers. Just optimise the hell out of it, please.

Finally: the community. While Typesafe dropped a small comment about the community in its response, its really not an issue that they can solve, though I do think it will greatly effect the measure of their success in the long term. Really, the comments in Coda's email should be a wake up call to the Scala community at large: a sizable Scala software development team, full of very smart people who've written some very scalable and successful software, found the Scala community to be so fractured and unhelpful that they eventually decided to ignore it and, I would assume, not be a part of it. That's not just a loss for the community, but also a warning, because for every developer that finds the community unhelpful and so decides to program Scala in his own microcosm, there will be numerous others who decide to not bother with Scala at all for the same reason. This alone could be a weighty enough issue to relegate Scala to a hobby language in the long term rather than seeing wide-spread adoption in the enterprise community.



Hope and Trepidation

When I originally read through Coda's email I was nodding my head in agreement and hoping that Typesafe would be listening carefully and would take it as an opportunity to shift their focus, maybe just temporarily, but long enough to knock over these major objections. Unfortunately, when I read through Typesafe's response, I didn't see any real hint that they plan to fix the problems that I find most annoying. In some cases I even saw excuses about why they won't be doing anything. I don't think "We're focusing on making sbt better" is  a response to "Why isn't there decent Maven support?". I know they've been meeting with influential Scala teams in the days since this response, I just hope they listen to what they've got to say.

So now I'm left feeling a little unsure about Scala. Will it continue to improve for me and people like me? People who like to use IDEA + Maven, not Eclipse + sbt, who are educated in creating applications rather than composing mathematical proofs? Or is the current state of the art in Scala, along with its broad range of minor but resonating annoyances, what I should expect to still be grappling with in five years time? Only time will tell whether Typesafe can navigate this wave of criticism and find a promised land of general popularity, but I think it is an indication that Scala's window of opportunity has entered the waning phase, and now is the critical time at which to capitalise on the extant interest.

What do YOU think?
Do you sympathise with the Yammer team's frustrations?
Are you confident that Typesafe will listen and respond to current criticisms with relevant and prompt action?

Wednesday, October 26, 2011

Top 10 Reasons Java Programs Envy Scala


I presented a talk at the 2nd meeting of the new ScalaSyd Meetup last night. I talked through the "Top 10 Reasons Java Programs Envy Scala" in an attempt to give Java developers a taste of some little things that could make them much more productive if they switch to Scala.

If you'd like to watch the Prezi, or listen to the talk (or both!), here are the links:

Presentation: Top 10 Reasons Java Programs Envy Scala (Graham Lea)

Audio Simulcast: Top 10 Reasons Java Programs Envy Scala (Graham Lea)

At the end of the talk, I mention that people who are tempted to learn Scala might want to look at my blog post, Graham's guide to learning Scala.

If you'd like to have a look at the code examples used in the talk you can view them on or clone them from GitHub.

Tuesday, October 11, 2011

Presenting at ScalaSyd, October 26

In two weeks' time I'll be presenting a talk at the recently-formed ScalaSyd Meetup. The title of the talk is "Top 10 Reasons that Java programs envy Scala"; the synopsis: "A whirlwind tour through 10 productivity-increasing features of Scala that aims to inspire Java developers to jump on the Scala bandwagon for their own coding pleasure."

There will be some other talks, Atlassian are providing the venue, pizza and drinks and JetBrains have donated some swag to dish out. It should be a good night so if you'll be in Sydney on Wednesday October 26, make a plan to drop in and make sure you RSVP on Meetup.com. Hope to see you there!

Wednesday, June 1, 2011

Introducing SodaTest: Spreadsheet-Driven Integration Testing for Scala and Java

I'd like to reveal what I've been working on in my spare time for the last couple of months.

The Announcement

SodaTest: "Spreadsheet-Driven Integration Testing", is an open-source framework for creating Executable Requirements for Integration and Acceptance testing in Scala and Java.

The impetus for starting this project was to attempt to create a tool that improves on Ward Cunningham's Framework for Integration Testing, "FIT". As an 'Executable Requirements' testing tool, it can also be considered as an alternative to Fitnesse, Concordion, RSpec, Cucumber, JDave, JBehave, SpecFlow, and Thoughtworks' Twist.

The Background

We used FIT in anger when I first arrived at my current workplace over four years ago. Since then I've watched the team become first dissatisfied with it, then scathing and fearing of it, before abandoning development of new FIT tests in place of Integration Tests written in JUnit. Nevertheless, we all still felt that Executable Requirements were a Good Thing and made a couple of failed restarts in trying to get back on the wagon.

From my own perspective, many of our issues (but not all) were to do with the tool. I identified two main issues that I'd seen hurt people over and over: the input format and the programming model. So I set out to create something that solved these two problems while remaining fairly close to what I think is a great foundation in FIT.

The Result

The result is a tool I've called SodaTest. It uses spreadsheets, in the form of comma-separated value (CSV) files, as the input format. The contents of the spreadsheet are basically small individual tables, much like what would appear in a FIT test. There is a required but simple structure to the tables and a minimum of special words and symbols to provide some context to the parser.

I also aimed to keep the programming model as simple as possible. I tried to make sure there is only noe sensible way things could be done, so as not to confuse developers with options. I've gone to lengths to ensure developers of Fixtures will have to do a minimum of work by having the framework do a lot of boilerplate work for them. Lastly, I've structured and named everything in a way that I believe will guide developers in the right direction (by which I mean away from mistakes that I have made in the past while writing FIT tests).

I've also taken the time to add a little sugar here and there that I thought was missing from FIT, for example integration with JUnit and a more comprehensive set of built-in coercion strategies for converting strings into strong types.

I'm quite pleased with the result. (I wouldn't be telling people about it if I wasn't!) Yesterday I released version 0.1 of SodaTest and people should be able to use this first release of SodaTest to create tests that do almost everything that FIT could do, but with less effort in creating the tests, writing the Fixtures, and getting the whole lot executing in their environment.

You can find out more about the motivation for SodaTest and the features it includes by reading the README on GitHub.

While SodaTest is written almost entirely in Scala (and the most benefit will be gained by using Scala as the language for writing Fixtures), I've also written the sodatest-api-java extension that allows SodaTest Fixtures to be written in Java. There is one limitation where Scala is (currently) still needed, but I reckon 95% of Fixtures should be able to be written entirely in Java if that is something you care about.

The Next Steps

The next steps for SodaTest are clear to me: Dogfood, Broadcast, Feedback and Evolve.

I want to convince my team at work to start experimenting with Executable Requirements again using my home-grown tool; I'd love it if other people in the Scala and Java communities could download this tool and give it a little tryout during their next iteration or two; I want to hear Feedback from people about what's good about SodaTest, what needs more work and whether there's parts that are just plain horrible; and, if the feedback is positive enough to consider SodaTest a preliminary success, I want to continue improving it in the areas where it's still holding people back.

There is already a Roadmap of possible features to add, but now it's really time to get it in people's hands and find out from users what is the next most important thing it needs to do.

Try It Out!

If you're a Scala or Java software developer and Executable Requirements are either a passion of yours or something you've been wanting to try out, why don't you give SodaTest a try? You don't have to commit to it, just write a couple of tests with it, get them running, then passing, and send me some feedback. All feedback is useful, even if you think it sucks! (As long as you tell me why.)

To get started with SodaTest, I suggest you:

<repositories>
<repository>
<id>sodatest-github-repo</id>
<name>SodaTest repository on GitHub</name>
<url>http://grahamlea.github.com/SodaTest/m2repository/ </url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.sodatest</groupId>
<artifactId>sodatest-api</artifactId>
<version>0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.sodatest</groupId>
<artifactId>sodatest-runtime</artifactId>
<version>0.1</version>
<scope>test</scope>
</dependency>
</dependencies>

Sunday, May 22, 2011

Explaining Scala to Your Wife Through Knitting

On Friday night I was sitting in my kitchen coding up some Scala. (Oh, what excitement a having small, sleeping child brings to Friday nights!)

My wife, who is a die-hard knitter, came into the room and, having seen me do little in the evenings for the last few years except code Scala, asked, "Is Scala just the bee's knees?"

My response, purely from reflex, was "No. CODING is the bee's knees!"

"Sure," she said (with a roll of the eyes, I suspect), "but is it like knitting something really interesting? Compared to Java, I mean?"

"Not quite," I said, "it's like if you had electric knitting needles that would let you start off the row and once you've done the interesting bit, the needles take over and do the rest of the row for you. So you'd just knit the interesting bits, not the dumb bits. With Java, though, you spend a lot of time writing dumb stuff."

"Right," she said, "that would be cool."

Yes, it would be cool. Sadly for knitters, electric knitting needles do not exist. Java programmers, on the other hand, have the freedom to use Scala if we want to stop doing dumb stuff.

How would you explain Scala to your wife?

Monday, May 16, 2011

Scala's Match is Not Switch++

Scala's match operator is a beautifully powerful beast. It can do some really sophisticated stuff with very little effort. However, if your introduction to 'match' was along the lines of, "It's like Java's 'switch', but better", then I want to offer a word of caution. I'll show an example where this thinking caused problems for me, briefly explain match and explain how I look at it now to prevent this confusion for myself.

A (Bad) Example
Some things can look quite straightforward, but at runtime act quite differently from how they look. You might call these bugs. Take the following snippet as an example. What do you think this prints out?

object TestingObject {
def main(args: Array[String]) {
val testValue = "Boris"
val inputValue = "Natasha"
List(inputValue) match {
case List(testValue) => println("Match!")
case _ => println("No match")
}
}
}
Because you're a smart alec and you know what makes for an interesting blog, you have probably correctly guessed that this prints out "Match!".

Let's try and get a little more information...

object TestingObject {
def main(args: Array[String]) {
val testValue = "Boris"
val inputValue = "Natasha"
List(inputValue) match {
case List(testValue) => println("Match! testValue = " + testValue)
case _ => println("No match")
}
}
}
The code now prints "Match! testValue = Natasha". This gives us a bit more insight into what's going on. Obviously the testValue that is defined in the case expression is not a reference to the original val testValue but a declaration of a new reference with a different scope.

My mistake when I wrote this code was to believe that everything that I put between case and => was an input to the matching algorithm, i.e. it was going into some == or .equals() that happens under the hood. This is true in Java's switch statement, where everything in the case must be a constant, but it's certainly not how things work in Scala's match.

New Perspective
I prefer now to think of match the other way around to how it was first introduced to me: I now consider the use of an explicit extractor object to be the normal case, and I think of any other form of case expression, such as matching against a constant value, as syntactic sugar for some built-in, implicit extractor.

When you use an extractor object, you have an object that defines an unapply() function which accepts an object of the type you are matching as a parameter. The unapply() function can either return a Boolean or an Option. If it returns a Boolean, then true means the argument is a match and false means that it wasn't. If it returns an Option, then None means that it wasn't a match, while a Some indicates it did match. Not only this, but the object contained in the Some becomes available to the expression on the right of the =>, assuming you give it a name in the case expression. I think this is the most significant difference between switch and match: In Scala, the case expression has outputs.

My problem in the example at the start was caused because I thought of List(testValue) in the case expression as an input, but it's not. It's actually the name of an Extractor object (List) and a name given to the output of that Extractor (testValue).

My new way of thinking is to pretend that everything in a Scala case is an extractor. So when I look at a case that is matching a plain old constant, I think to myself, "That's calling an extractor that returns true if the input value equals the constant. If I see case x: Int => I think, "That's calling an extractor that returns Some(x) if the object is an Int or None if it's not.

Re-Program Yourself
So, my suggestion is to rid yourself of any notion that Scala's match is like "switch on steroids". That view can lead to the false belief that match is a switch that can deal with all kinds of interesting, non-constant input values. In actual fact, the cases in match are all about Extractors, not inputs, and matching against constant values in the same way as switch is best thought of as just a nice little trick that the compiler does for you to hide the Extractor.

Want to Learn More?
If you suspect that a bit too much of your Scala knowledge may come from blogs that were comparing it with Java, reading one of these books might help:

From Amazon...


From Book Depository...


Monday, January 10, 2011

Scala == Effective Java ?

I started reading Joshua Bloch's Effective Javalast week. I'll have to admit that I haven't read it before, but only because I've been told by several people, "you already do most of what's in there anyway." Seeing as we tell all the new recruits to read it, I thought I should actually flip through it myself so I know what's in there.

Books of best practices are always written in relation to domains that have many possibilities for bad practices (choosing otherwise would make for a very short book). Reading the first chapter of Effective Java, I was amused as I realised that, if you're coding in Scala instead of Java, many of the book's recommendations are either unnecessary, because Scala doesn't permit the corollary bad practice, or built into the language of Scala, or made easier to implement than they are in Java. This isn't a criticism of the book, but an observation that the state of the art is moving on, and Java is being left behind.

From the first 25 items in the book, here are my notes on practices that either become easier to follow or unnecessary if you are using Scala:

Item 1: Consider static factory methods
One of the four advantages given for static factory methods is that construction of classes with type parameters is briefer through static methods because the type parameters can be inferred on a parameterised method call. Scala solves this one by inferring type parameters on constructors, but not only that. It infers LOTS of types, almost everywhere: fields, local variables, method return types, anonymous function parameters - all can usually have their type inferred from the context, meaning that Scala code has a lot less declarative noise, while still remaining statically type-checked.

Item 2: Consider the Builder pattern instead of long constructors
Joshua writes himself that the Builder pattern simulates the combination of named parameters and default parameters that are found in other languages, and Scala supports named and default parameters. What he means by "simulates" is that you need to write a whole extra Builder class in Java to get the nice Builder effect at the client site, whereas in Scala, you essentially get a Builder for free every time you write a constructor.

Item 3: Enforce Singletons
While code-enforced singletons have gone out of fashion a bit with the popularity of IoC containers, they're still around a lot and these rules are still important. Scala supports singletons at the language level, providing the 'object' keyword which, substituted for the word 'class' in a declaration, will compile a singleton object into your code instead of a class. The generated object follows all of Josh's recommendations, including deserializing to the same instance (as long as you use Scala's @serializable rather than extends java.io.Serializable)

Item 4: Enforce non-instantiability with private constructors
There's really only two cases where you want to do this: singletons (see above), and utility classes, which are really just singletons that have no state. Either way, Scala's 'object' keyword for creating singletons is the simple answer.

Item 5: Avoid auto-boxing
The recommended panacea for unwanted auto-boxing is to prefer primitives wherever possible. Now, Scala is a purely object-oriented language, which means there are no primitives, and all numbers, characters and booleans are represented at the language level as objects. However, Scala uses of these primitive wrapper objects compile to byte code which uses Java's primitives wherever possible, so this recommendation is implemented for you by the Scala compiler.

Items 7, 8 and 9: Overriding toString, hashCode and equals
If you're authoring an immutable data structure, declaring your Scala class as a case class will tell the compiler to automatically implement toString, hashCode and equals for you, along with an unapply() method that can be used in a pattern matching clause. (There are some disadvantages to using Scala's case classes, but I believe they work well for most situations.)

Item 11: Override clone() judicously
While Scala as a language doesn't provide an answer to this one, it's considered best-practice Scala to favour immutable types, with transformation being much favoured over mutation. Following this principle will reduce the need to ever use clone(), because immutable objects can be shared among many clients and threads without the shared-mutable-state worry that might cause you to consider cloning something.

Item 14: Use public accessors methods rather than public fields
While Scala appears to have public fields - and indeed to make fields public by default - in fact Scala implements Bertrand Myer's "Uniform Access Principle", with all access to fields (which are in fact all private) being made through accessor and mutator functions that have the same name as the field. In other words, the compiler writes get and set methods for you and everything that looks like field access in your code actually goes through these methods.

Item 15: Minimize mutability
As already mentioned, it's considered Scala best practice to shun mutable state as much as possible. One of Josh's four recommendations for decreasing mutability is to make values final wherever possible. All Scala fields and local variables must be preceded by either 'val', indicating immutability (of the reference), or 'var', indicating that the reference can change. (Function parameters are always vals, and hence final.) Forcing programmers to make this choice when each variable is declared encourages the practice of using a lot of immutability, compared to final which is an optional modifier and seen by many as extra noise in most declarations.

Item 18: Prefer interfaces to abstract classes
Scala has traits - abstract classes that essentially allow multiple inheritance of function definitions (as opposed to interfaces, which only inherit function declarations). The possibility of multiple inheritance discounts quite a few of the disadvantages Josh raises against using abstract classes in Java. Of course, it also introduces some new issues, and exacerbates some others, like those Josh lists in Item 16 about preferring composition+delegation over inheritance. Multiple inheritance is a double-edged sword, for sure.

Item 21: Use function pointers
Scala, as a functional language, has functions as first-class members of the language, with every function naturally being available as an object (same as what Josh calls a function pointer) should the need arise. It also supports anonymous, inline functions, which, if available in Java, could reduce current "function pointer" logic like this:
new Thread(new Runnable() { public void run() { System.println("Running"); } } );
down to something like this:
new Thread({System.println("Running")})

Item 23: Don't use raw generic types
Scala doesn't allow you to write code that uses raw generic types, even if those types are defined in Java: it just won't compile. For what it's worth, raw generic types are not a feature, but merely an artefact of backwards-compatibility. Scala, not trying to be backwards-compatible with Java 4, just doesn't need raw types and, as a result, is able to provide stricter type safety for type-parameterised classes and functions.

Item 25: Prefer Lists over Arrays
While you should probably still prefer Scala's List class to Arrays for most applications, Scala prevents the chief problem cited with Java's arrays. In Java, you can cast a String[] to an Object[] and then assign a Long to one of the entries. This compiles without error, but will fail at runtime. In Scala, however, arrays are represented in source code as a parameterized class, Array[T], where T is an invariant type parameter. This basically just means that you can't assign an Array[String] to an Array[Object], and so Scala prevents this problem at compile time rather than choking at runtime.

Scala == Effective Java ?
So I'm going to put this question out there:
If 'Effective Java' is considered essential reading, and the best practices in it are the de facto standard for writing good programs, shouldn't we all be giving serious consideration to switching to a language that is so very close to Java, but makes good programming even easier?

Want to learn more?
From Amazon...
From Book Depository...

Thursday, December 16, 2010

Graham's Guide to Learning Scala

It's a pretty widely-accepted view that, as a programmer, learning new languages is a Good Idea (tm). Most people with more than one language under their belt would say that learning new languages broadens your mind in ways that will positively affect the way you work, even if you never use that language again.

With the Christmas holidays coming up and many people likely to take some time off work, this end of the year presents a great opportunity to take some time out from your week-to-week programming grind and do some learning.

With that in mind, I present "Graham's Guide to Learning Scala". There are many, many resources on the web for learning about Scala. In fact, I think there's probably too many! It would be quite easy to start in the wrong place and quickly get discouraged.

So this is not yet another resource to add to the pile. Rather, this is a guided course through what I believe are some of the best resources for learning Scala, and in an order that I think will help a complete newbie pick it up quickly but without feeling overwhelmed.

And, best of all, it has 9 Steps!

[Note: Many of the resources have a slant towards teaching programmers that know Java, but I imagine if you know any other popular OO language like C++, C#, Ruby, Python, Objective-C or Smalltalk, you shouldn't have a problem picking it up.]

Are you ready? Here goes...

Step 1: Lay the Foundation

Read 'Introduction to the Scala Language' on scala-lang.org

This single page is a succinct but dense description of Scala and will let you know what you're in for, and why you should keep going.


Step 2: Get the Tools

Download and install the latest Scala release

Download and install the latest IntelliJ IDEA *Community Edition* release

Open IDEA and install the 'Scala' plugin


Step 3: Hello, World!

Create a new IDEA project with a Scala module.
Create a new file called HelloWorld.scala and paste in the following code:

object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}

Hit Ctrl-Shift-F10 to run it.
Congratulations! First Scala program done and dusted!


Step 4: Commute your Java skills to Scala

Read Daniel Spiewak's 'Scala for Java Refugees' series.

This should give you enough knowledge and experience with Scala syntax to be able to write Scala that does most of the things you can do in Java.

Make sure you enter the code examples into IDEA and try them out as you go. I suggest typing them out instead of copy-paste, because that's likely to give you exposure to common syntax mistakes and compiler errors.


Step 5: Open Your Eyes

Read through the 'Tour of Scala' on scala-lang.org

These short pages will give you some exposure to some of the more advanced features of Scala. Don't worry if you don't understand everything - just keep reading. You're not trying to learn how to use all these things, just to know that they're around.


Step 6: Learn the Basics, the Ins & the Outs

Read chapters 1 to 8 of Dean Wampler & Alex Payne's 'Programming Scala' (O'Reilly)

This is where the learning gets heavy. We're talking about more than half a book here. You'll learn everything from basic syntax (some of which you'll already know from the Refugees series) to Scala's more advanced patterns for object-oriented programming, an introduction to Scala's functional programming capabilities and some of the curly edges of Scala's type system.

Again, make sure you try out running the code samples in IDEA. I suggest you also have a play around with some of the concepts in your own little test classes. Any time you find yourself thinking "I wonder if I can use this feature to do this?", grab a keyboard and find out for yourself.


Step 7: Open the Dragon Scroll and Release your Scala Fu

Take a break from learning and do some hacking!

Think of a simple idea that you'd like to implement in Scala, then code it! (Seriously, I recommend keeping it REALLY simple.) If you can't think of something yourself, you can steal my idea of writing a function to perform word-wrapping.


Step 8: Take a Walk around the Grounds

Read the rest of 'Programming Scala' (chapters 9 to 14)

The rest of the book covers some of the peripheral libraries and concepts in Scala that contribute to making it a great language, like Agents for multi-threaded programming, "herding" XML input and output and building blocks for creating domain-specific languages, as well as reviewing some of the tools that have sprung up in the Scala ecosystem.


Step 9: Go Forth and Hack!

This is where the directed part of the journey ends, but hopefully it's only the first step.

What you do with Scala next is up to you, but by this point you know more than enough about Scala to start using it seriously at home or even at work, for fun, or for making some serious cash! If you do make some serious cash by hacking Scala, please remember how it all started and send a little monetary "Thank you" my way. ; )


Addendum: Getting Help

Perhaps it was a little presumptuous of me to effectively say "go away now and code". Chances are, you'll need some help as you keep experimenting, learning and doing more and more cool stuff with Scala.

The two best places that I've found to connect with other Scala users are the scala-user mailing list run by scala-lang.org and, for curly technical problems that you just can't figure out yourself, stackoverflow.com. Actually, reading through other people's Scala questions on Stack Overflow can also be a great way to pick up new ideas!


Want to learn more?

From Amazon...

From Book Depository...

Tuesday, October 26, 2010

SpringOne 2010: Introduction to Spring Roo

I spent the second-last week of October at SpringOne 2GX 2010 in Chicago and I thought some of you might get something useful out of my notes. These aren’t my complete reinterpretations of every slide, but just things I jotted down that I thought were interesting enough to remember or look into further.

Introduction to Spring Roo
presented by Rod Johnson and Stefan Schmidt

I didn’t take a whole lot of notes in this session because it was entirely demo, however the ease with which Spring Roo can quickly create working (though rudimentary) CRUD web applications was quite amazing.

Rod gave some good explanation around the magic that makes it happen. Basically, the commands given to Roo result in it generating two sets of files. One set is the Java files that the developer can work with, for example adding business logic, without worrying that Roo might overwrite the contents of these files later (it doesn't). The Java classes are annotated with Roo annotations, e.g. @RooEntity, @RooToString, @RooJavaBean, that Roo uses to determine what additional functionality it will add to the annotated class.

The functionality that Roo adds in is actually defined in aspects that are maintained in files juxtaposed with the Java files. From what I could tell, there is basically an aspect for each Roo annotation on each Roo class, e.g. Customer.java has CustomerRooEntity.aj, CustomerRooToString.aj, etc. These aspect files are updated or re-written by Roo automatically as the Roo model is changed, so if you were to make any changes to them your changes to the aspect source files they would get wiped out by the next Roo operation. This is what allows Roo to provide round tripping (although, in truth, I think it’s the illusion of round-tripping) : it generates an empty, annotated class that you can edit to your heart’s content without fear of interference from Roo’s automated operations, while allowing all the Roo-controlled stuff to be “round-tripped” by keeping it in aspects that are kept up-to-date with Roo-controlled changes.

At first I thought this meant that every Roo class had several aspects over it at runtime, which sounded like a performance nightmare, but I found out later that the aspects are applied at compile –time, essentially acting as source mix-ins to the Java class file that will deployed.

I spent a little time thinking about how one might try to achieve a similar thing with Scala. The first thing that occurred to me is that you wouldn’t need to use aspects. Because Scala supports multiple inheritance, the extraneous data and functions that Roo is storing in aspects could, in Scala, just be separate traits that the main class extends. This would also alleviate the need for the annotations, if you wanted to get rid of them. (I supposed the annotations have the advantage that they're not actually tied to the code in the aspects. I'm fairly sure you can remove and introduce the annotations in the Java files and the aspects will disappear and reappear accordingly (that one part is true round-tripping), while the same would not be true of traits - they would have to exist before you could extend them, unlike the aspects.)

The other little thing I thought is that, using Scala, the @RooJavaBean functionality would be relatively unnecessary, seeing as Scala already has the @BeanProperty annotation to do the same thing (albeit on a per-field basis). So while the Roo code generation saves a lot of boilerplate for Java developers, I think Scala devs can achieve pretty much the same thing with some sensible common traits and minimal extra effort. (I'm just thinking about the entity stuff we looked at here. It's likely there's Roo goodness in the web tier for which Scala cannot naturally provide a neat alternative.)

At the end of the presentation, they showed the latest version of the Spring Insight project, I’m guessing because they used Spring Roo to develop it. (?) It looks very cool, and the level of detail you can browse down to is amazing, e.g. you can see the JDBC calls issued during a web request. I've found in the past that the problem with tools that have this much data is always in figuring out how best to represent it all sensibly and aiding the user in selecting where to drill down. From the little I’ve seen, some of the charts they have seemed to do a good job of this. It's definitely worth a try back home to see what it can do. They are currently working on a version that will be able to be deployed against production systems.

Tuesday, August 31, 2010

Things I Love About IntelliJ IDEA: The Impossible is Possible

The features I've written about so far are the ones that I use really often and that I find make the biggest difference for me when I use IntelliJ IDEA. Some of them are a bit mundane, but when I have to code without them I often get the feeling of being bogged down in typing boilerplate.

But there is another side to IntelliJ - an exciting side! IDEA has a whole host of features which, to me, are bordering on mind-blowing. There are quite a few features in IDEA that are so impressive that I don't just think, "That's a clever idea. I'm glad they put that in." What I really think is, "How the hell did they even IMAGINE that that was POSSIBLE?!" Seriously, the Jetbrains guys have implemented tools that I would have laughed at if they were proposed to me, just from the sheer audacity of the ideas and the complexity that I imagine would be involved in implementing them.

One domain where they have been impressing me lately is in their Hibernate integration. If you tell IDEA about a datasource that your Hibernate entities should be able to map to, it can do some cool things like tell you that no table exists with the same name as your entity, or that the column name in your @Column annotation doesn't match any column in the database table. There's also the HQL console, where you can run HQL queries against your database, complete with code-completion from your domain model. Both of these are "Cool, that's useful" features, but I imagine your mouth is not yet agape.

Then they go to the next level: the same code completion that's available in the HQL editor is also available write in the middle of your code using language injection. That's right, those Strings in your Repository classes are no longer just Strings - that first double quote now denotes the point at which Java stops and HQL starts, and IDEA will give you all the help you need to write a query that is correct both syntactically and in respect of your domain model, with name completion, underlining of errors and meaningful error messages. (To enable HQL editing in a class just hit Alt-Enter, select 'Inject Language', then 'HQL')

But after the Jetbrains guys implemented that awesome integration, they got bored, so they had to think of something even more amazing to integrate. Now I see that in the upcoming IntelliJ IDEA X, they have added similar integration to queries created using Hibernate's Criteria API. The ingenuity involved in this feature astounds me - IDEA is observing the annotations on Hibernate entities, parsing Java code and recognising a Criteria query, then building enough understanding of that query and linking it in with the knowledge from the entity classes to be able to make suggestions about the possible and legal properties and relationships that could be queried. It's another example of IDEA being so intelligent that it probably knows more about my code than I do, and the guys have probably re-written half of Hibernate in order to give it to us.

As I said, this is just one domain (no pun intended) that has been impressing me lately. IntelliJ IDEA is full of little nuggets likes this where the Jetbrains developers have dreamed up and then delivered features that are useful so far beyond any little improvements or tweaks that I could have requested as a day-to-day user. This isn't the product of a team of developers tirelessly implementing feature requests from users - it's the constantly evolving creation of a group of highly visionary people who intimately understand the day to day tasks of a coder but are also able to rise above the detail and imagine a better future where the tools don't just help out with the boilerplate but also start to take on some of the heavy lifting.

Thursday, August 5, 2010

Things I Love About IntelliJ IDEA: Buffer History

With IntelliJ IDEA's Buffer History or "Paste From History" (Ctrl-Shift-V), you can copy multiple snippets and have all of them available for pasting later on. There's no special trick to copy things into the Buffer History - everything copied goes in there. To paste something from the History rather than the lastest copied snippet, just press Ctrl-Shift-V to see the list of available snippets. It's great for a couple of different uses.

Firstly, there are those situations where you need to copy multiple snippets from one source and paste each snippet one or more times at some other destination. For example, you might need to copy multiple sections from one file to another file, which would normally require you to copy one section then paste it in the destination, then come back to copy the other section then paste that into the destination. Or you might be building up a unit test and you have to add two separated lines to each test case, which you would normally do by traversing all the tests once to paste the first line and a second time for the second one.

With the Buffer History, you can just copy each of the sections from the source one after the other, then traverse to the destination and paste each section where it should go. No more jumping back and forth between files, and no more need to traverse the one file multiple times to paste different snippets.

Secondly, the Buffer History helps out in a couple of facepalm scenarios that I often encounter and with which I hope you'll sympathise:
#1: "Urr... I need to paste that thing that I pasted in that other file ten minutes ago. What was that file called again?"
#2 "Aw crap. I just hit Ctrl-C instead of Ctrl-V."

If you encounter either of these in IDEA, just hit Ctrl-Shift-V.
Problem solved.
Facepalm prevented.

I recommend increasing the size of the clipboard history to at least 30. (Search for 'clipboard' in IDEA's Settings.) It doesn't cause any problems to have a larger history and having everything you've copied for the last hour still in the clipboard can save quite a bit of searching.

Thursday, February 25, 2010

How to Convert a Java List to a Scala List (actually... let's not do that)

If you're using Scala and still making use of pretty much any Java library, you'll pretty soon come up against this problem: you're Java library has returned you a java.util.List, but you want to use the awesome methods contained in Scala's scala.List (soon to be scala.collection.immutable.List).

I'll show you how to do what you want in a second, but first, and importantly, I need to explain that what you actually want to do is NOT convert a Java List to a Scala List. Why? It's because, despite the name similarity, they're actually very different things...

The difference is that Java's List is an interface, while Scala's List is an implementation. The List interface in Java represents a concept: a collection of elements that maintains insertion order (i.e. a sequence) and allows, among other things, random access to its elements. The most commonly used implementation is ArrayList, which is mutable (i.e. invoking add(element) changes the existing list) and has constant-time random access. Unlike Java's List interface, Scala's List is a specific implementation of a sequence. In that sense, it is a parallel to ArrayList, but in many other senses, it's nothing like it. The List class imported by default in Scala is an immutable linked list - it can't be changed after it's been created and operations requiring random access take linear time. Scala's List is not a direct substitute for Java's List and it's extremely different to ArrayList as well. So, what to do?

Most people want to convert their Java List to a Scala List just so they can use cool Scala functions like map(), filter(), find(), foreach(), foldLeft() and flatMap(). And that's a perfectly good excuse. But if you look into the Scala API, you'll see that all of these useful methods are available on any class that implements the Iterable trait. (From Scala 2.8, they are also available on the Traversable trait, which the Iterable trait extends.)

If we look a bit further into the Scala API, we'll see that there's also a trait called Seq, which is a slightly better parallel to Java's List than the Iterable or Traversable traits. So what you really want to end up with when you bring your Java List into your Scala code is a Scala Seq, not a Scala List.

That's enough jibber-jabber. I'm sure you've learnt your lesson.

Here's a great way to convert a Java List to a Scala Seq in Scala 2.7:

scala> var javaList = new java.util.ArrayList[Int]()
javaList: java.util.ArrayList[Int] = []

scala> javaList.add(3)
res0: Boolean = true

scala> javaList.add(4)
res1: Boolean = true

scala> javaList.add(5)
res2: Boolean = true

scala> val scalaSeq = new collection.jcl.BufferWrapper[Int]() {
def underlying = javaList
}
scalaSeq: java.lang.Object with scala.collection.jcl.BufferWrapper[Int]{def underlying: java.util.ArrayList[Int]} = [3, 4, 5]

scala> println(javaList)
[3, 4, 5]

scala> println(scalaSeq)
[3, 4, 5]

In Scala 2.8, the EPFL LAMP guys have realised the importance of this kind of conversion and gone one better by providing a class full of conversions that do exactly what we want, like this:


scala> var javaList = new java.util.ArrayList[Int]()
javaList: java.util.ArrayList[Int] = []

scala> javaList.add(3)
res0: Boolean = true

scala> javaList.add(4)
res1: Boolean = true

scala> javaList.add(5)
res2: Boolean = true

scala> val scalaSeq = scala.collection.JavaConversions.asBuffer(javaList)
scalaSeq: scala.collection.mutable.Buffer[Int] = Buffer(3, 4, 5)

scala> println(javaList)
[3, 4, 5]

scala> println(scalaSeq)
Buffer(3, 4, 5)

Of course, so much of the appeal of Scala is attributable to having to write less code, so it would be nice to not even have to invoke these operations within functions but instead to have implicit functions that will perform the conversions whenever they're necessary.

In Scala 2.7, the implicit conversion can be defined like this:

implicit def javaList2Seq[T](javaList: java.util.List[T]) : Seq[T] =
new BufferWrapper[T]() { def underlying = javaList }

And in Scala 2.8, all you need to do is import the existing implicit functions!

import scala.collection.JavaConversions._

Monday, January 18, 2010

How To Create a Webapp with Scala, Spring, Hibernate and Maven

Update: I've written a new blog entry with a link to code on GitHub that combines the latest versions of Scala, Spring, Hibernate and Maven. The original blog entry below is still a great walk-through for learning how to put together all the technologies from scratch.


The Technologies

So, this post is simply a recipe for combining four of today's most popular technologies: Spring, Hibernate, Maven and Scala.

In case you're new to some of these technologies, here's a REALLY quick overview:

Spring is a framework for creating enterprise applications that uses Inversion of Control, Dependency Injection, Aspect-Oriented Programming (including annotation-based transaction boundaries) and lots of flexible, highly-extensible components for building pretty much anything. Its Model-View-Controller (MVC) web framework has been a popular replacement for Struts.

Hibernate is an Object-Relational Mapping library, used to store data from Java objects into relational databases (and retrieve it again).

Maven is a Java-based and -focussed build tool that uses a common project lifecycle and a declarative Project Object Model (POM) to make it simple to build applications by defining only what needs to happen, rather than how it happens (which remains in the implementation details of its plugins).

Scala is a Functional/Object-Oriented hybrid language that executes on the Java Virtual Machine (JVM) and is becoming increasingly popular, especially with Java developers, mostly due to its concise syntax, static typing and seamless integration with the Java SE API.

The Task

The task is to write a simple webapp that can persist and retrieve an entity. The goal is to use the latest of everything, including Scala 2.8, Hibernate 3.2.7 with annotations and Spring 3 and it's annotation-based controllers for creating REST-ful webapps.

The first part of this tutorial is basically just a diary of the steps I took to create a working application using Maven, Scala, Spring and Hibernate. I won't do a lot of explaining because different readers will obviously have different knowledge about different technologies, but I've documented every single web page that gave me a useful piece of information in putting the whole thing together.

The second part is a documentation of all the little things that went wrong while creating the "how to". Including these in the main introduction would just be a distraction but I'm sure the fixes I had to discover and correct will be useful to a few people scouring the internet for solutions one day.

Enough chatter, let's write some code…

No, wait!
Let's GENERATE some code! :)

Step 1: Use Maven to Create a Project

If you don't already have Maven installed, you'll need to download and install it and put its bin/ directory on your path.

References:
Download Maven

I already had it installed (although I don't remember installing it - is it standard on a Mac?) so I went to the directory where I wanted the project to live and created a new Maven project using the Scala archetype with this command:
mvn org.apache.maven.plugins:maven-archetype-plugin:1.0-alpha-7:create \
-DarchetypeGroupId=org.scala-tools.archetypes \
-DarchetypeArtifactId=scala-archetype-simple \
-DarchetypeVersion=1.1 \
-DremoteRepositories=http://scala-tools.org/repo-releases \
-DgroupId=au.com.belmonttechnology -DartifactId=scala-spring-hibernate

References:
Scala Blogs: maven for scala

Then I went into the directory and built the project:
mvn clean package

After downloading lots of plugin code, it successfully compiled the App and AppTest classes and then the AppTest.testKO test case failed. No need to panic - the implementation of this generated Test shows that it's meant to fail. It proves that Maven is running the test.

Too easy. Onwards and upwards...

Step 2: Get Scala and Maven Working in Your IDE

I'm using IntelliJ IDEA 9 Community Edition (it's free!). I was dead-simple to create a new IDEA project using the Maven POM that was just generated. Here are the steps:

1. New Project
2. Import project from external model
3. Maven
4. Choose directory
5a. Only tick 'Import Maven projects automatically' and 'Use Maven output directories'
5b. Use 'process-test-resources'
6. Finish!

You'll also need to make sure you've got a Scala plugin for your IDE installed and working. In IDEA, you can get one just by going into the Plugins config pan, searching for Scala and downloading the one that pops up.

To make sure the IDE was set up properly, I opened the App class, and changed it to look like this:
object App {
def main(args: Array[String]) {
println( "Hello World!" );
}
}
and then ran it (in IDEA use: CTRL-SHIFT-F10)

I like to live on the edge, and I noticed that the Scala version that the Maven archetype had delivered me was 2.6.1. Pfh!

So, I opened up http://scala-tools.org/repo-releases/org/scala-lang/scala-library/ in Firefox and found the latest and greatest (and hopefully somewhat stable) Scala release version, which was 2.8.0.Beta1-RC7 at the time of writing. I copied this version into the top of pom.xml, where the archetype had written:
<scala.version>2.6.1</scala.version>
I ran the App class again to make sure it's still working

Having proved that the App class was working - I DELETED IT!

Step 3: Create a Spring Web Application

I added the following two entries into the <repositories> section of the POM:
<repository>
<id>com.springsource.repository.bundles.release</id>
<name>EBR Spring Release Repository</name>
<url>http://repository.springsource.com/maven/bundles/release</url>
</repository>
<repository>
<id>com.springsource.repository.bundles.external</id>
<name>EBR External Release Repository</name>
<url>http://repository.springsource.com/maven/bundles/external</url>
</repository>

References:
Obtaining Spring 3 Artifacts with Maven

Then I added the following line to the <properties> section:
<org.springframework.version>3.0.0.RELEASE</org.springframework.version>

and added the following dependencies to the <dependencies> section:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.context</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.transaction</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.web</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.web.servlet</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>

I wanted to get Spring working before I tried to integrate Hibernate, so I created a new package, au.com.belmonttechnology.spring.web, and created a new Scala class in there called HelloWorldController, and wrote this code:
@Controller
class HelloWorldController {
@RequestMapping(Array("/hello.html"))
def showHello = "helloPage"
}

References:
Mapping requests with @RequestMapping

I ran mvn clean package again to make sure this little guy compiled.

Then I created a src/main/webapp/WEB-INF directory and created a web.xml file with a basic DispatcherServlet setup:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="scala-spring-hibernate"
version="2.5">

<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/web-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>

</web-app>

References:
DispatcherServlet reference documentation
DispatcherServlet javadoc
Introduction to Spring MVC Web Framework
JSTL 1.2 and maven-jetty-plugin

Then I created the web-context.xml file that is used to initialise the Spring context for the DispatcherServlet. I set up a component-scan for the package that contains the HelloWorldController and inserted the same UrlBasedViewResolver configuration that everyone else in the world is using:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:component-scan
base-package="au.com.belmonttechnology.spring.web"/>

<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

</beans>

References:
Annotation-Based Autowiring in Spring 2.5
Annotation-based controller configuration
Spring Web MVC Views and resolving them

Then I created the JSP that the HelloWorldController was returning as it's view: src/main/webapp/WEB-INF/jsp/helloPage.jsp
<%@page contentType="text/html;"%>
<html>
<body>
<h1>Hello from ${pageContext.request.serverName}</h1>
</body>
</html>

References:
JSTL Implicit Objects
ServletRequest javadoc

And, finally, I changed the POM's packaging to be 'war':
   <packaging>war</packaging>

At this point, I was able to mvn clean install the project and everything builds, but there's no way of running the webapp...

Step 4: Start the Webapp with Maven using the Jetty Plugin

One of the easiest ways I've found of getting a webapp to run for testing is to use the Jetty Maven Plugin. All I had to do was add the Jetty plugin to the POM:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.0.2.v20100331</version>
</plugin>

References:
Jetty Maven Plugin

Then on the command line I simply ran:
mvn clean package jetty:run
and it all started up brilliantly.
I accessed http://localhost:8080/hello.html and saw a beautiful thing:

Hello from localhost

So, with my Spring 3 / REST / Scala app running on Jetty, I moved onto Hibernate…

Step 5: Get Hibernate Running in Spring

I added a dependency for the latest version of Hibernate and Hibernate Annotations to the POM:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.4.0.GA</version>
<exclusions>
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.4.0.GA</version>
</dependency>
I also added a couple of dependencies that Hibernate would need:
       <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.8</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.5.8</version>
</dependency>
Then I created a very simple Hibernate @Entity class in Scala:
package au.com.belmonttechnology.data

import javax.persistence.{GeneratedValue, Id, Entity}
import reflect.BeanProperty

@Entity
class Customer() {
@Id @GeneratedValue
var id: Long = 0

@BeanProperty
var name: String = null;
}

References:
Hibernate Annotations
JavaBean Properties in Scala

Next, I created a controller that would be able to serve a "Create New Customer" form, receive the POST submission from the form and redirect to a JSP that would display the newly-stored entity:
package au.com.belmonttechnology.spring.web

import org.springframework.stereotype.Controller
import au.com.belmonttechnology.data.Customer
import org.springframework.beans.factory.annotation.Autowired
import org.hibernate.SessionFactory
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.bind.annotation.{PathVariable, ModelAttribute, RequestMapping}
import org.springframework.web.bind.annotation.RequestMethod._
import org.springframework.web.servlet.ModelAndView

@Controller
class CustomerController {
implicit def sessionFactory2Session(sf: SessionFactory) =
sf.getCurrentSession();

@Autowired
var sessionFactory: SessionFactory = null

@ModelAttribute("command")
def createCustomerForFormBinding = new Customer

@RequestMapping(value = Array("/customers/new"), method = Array(GET))
def showNewCustomerForm() = "newCustomer"

@Transactional
@RequestMapping(value = Array("/customers/new"), method = Array(POST))
def createNewCustomer(@ModelAttribute("command") customer: Customer) =
"redirect:/customers/" + sessionFactory.save(customer) + ".html"

@Transactional(readOnly = true)
@RequestMapping(
value = Array("/customers/{customerId}"), method = Array(GET))
def viewCustomer(@PathVariable customerId: Long) =
new ModelAndView("customer", "customer",
sessionFactory.get(classOf[Customer], customerId))
}

References:
Spring @Autowired Annotation
Annotation-based controller configuration
Hibernate Session javadoc
Understanding the Spring Framework's declarative transaction implementation
Scala for accessing a Class at runtime
Spring ModelAndView javadoc

Then I created JSPs to match the views that I'd specified in the controller - newCustomer.jsp for submitting a POST to create a new Customer in the database:
<%@page contentType="text/html;"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<body>
<h1>New Customer</h1>
<form:form>
<form:label path="name">Name</form:label>
<form:input path="name"/>
<input type="submit" label="Create Customer"/>
</form:form>
</body>
</html>
and customer.jsp for viewing a Customer entity that's been retrieved from the database:
<%@page contentType="text/html;"%>
<html>
<body>
<h1>${customer.name}</h1>
<p>Might I suggest enhancing the system to support more than just a customer's name?</p>
</body>
</html>
References:
Spring Form Tag Library

I decided I need a quick and dirty in-memory database to test with, so I added the dependency for HSQLDB to the POM, as well as the Apache Commons Database Connection Pool:
       <dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.10</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2</version>
</dependency>
Then I wrote the Spring config for Hibernate, and a BasicDataSource (using HSQLDB) in a file called spring-context.xml…
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<tx:annotation-driven/>

<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:scala-spring-hibernate"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClasses">
<list>
<value>au.com.belmonttechnology.data.Customer</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
</beans>
.. and wired it into the web.xml using Spring's ContextLoaderListener:
   <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-context.xml</param-value>
</context-param>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
Lastly, I added an OpenSessionInViewInterceptor into the Spring configuration in web-context.xml and specified this as an interceptor on the DefaultAnnotationHandlerMapping:
...

<bean id="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list><ref bean="openSessionInViewInterceptor"/></list>
</property>
</bean>

...


References:
Understanding the Spring Framework's declarative transaction implementation
Spring Hibernate Tutorial
Unit-Testing Hibernate With HSQLDB
Introduction to Spring MVC Web Framework
OpenSessionInViewInterceptor

Then I fired it all up again with mvn clean package jetty:run, browsed to http://localhost:8080/customers/new.html and voila! I happily spent the rest of my evening delighting in entering new customers into my in-memory database. (Not.)

If you'd like to get your hands on this fantastic new application, you can download the source code from Belmont Technology (MIT licence).

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)


Problems, Problems, Problems

Okay, in all honesty, it was nowhere near as straightforward to create this simple webapp as the journal above makes out. There were a number of compilation errors, thrice as many runtime exceptions, and the number of Google searches required was approaching a googol. But for your benefit - either by help or by humour - I've documented below the error, cause and solution to all of the hitches I encountered along the way.

Problem 1: NoClassDefFound when running Scala App in IntelliJ

When I first tried to run the App class in IntelliJ, I got a NoClassDefFoundError as output.
At this point, I opened the Maven tab and tried to run the 'test' phase, which told me that I didn't have a Maven Home Directory set, so I went into the project settings and fixed that.
After this, I was able to run the 'test' phase successfully, and then the App class ran successfully, too.

Problem 2: Invalid URI / Invalid Authority trying to access the Maven repository

After first adding Spring to the POM, I got some errors in my Maven pane in IDEA. I tried running the compile goal and got the following Maven error in the console:
Invalid uri 'http:// repository.springsource.com/maven/bundles/release/org/springframework/org.springframework.context/3.0.0.RELEASE/org.springframework.context-3.0.0.RELEASE.pom': Invalid authority
I copied and pasted this URL into Firefox, upon which it did a Google search, which is an unusual thing to do with a URL. Looking closer, I realised there was a space after http:// in the repository URL that I'd pasted into the POM. I deleted the space and was able to run the compile goal successfully (although, at this point, there was nothing to compile!)


Problem 3: Type Mismatch in Scala annotation

When I first created the HelloWorldController and tried to run the mvn package phase, I got the following compilation error:
[ERROR] /Users/graham/Code/scala-spring-hibernate/src/main/scala/au/com/belmonttechnology/spring/web/HelloWorldConroller.scala:16: error: type mismatch;
[INFO] found : java.lang.String("/hello.html")
[INFO] required: Array[java.lang.String]
[INFO] @RequestMapping("/hello.html")

It was easy enough to figure out how to fix this - in Scala, annotation parameters that are an array require Array(…) around them. In Java, you're allowed to leave the curly braces out when there's only one value for an array in an annotation, but Scala (at the moment) always requires an actual array.

References:
Arrays in Scala annotation arguments

Problem 4: IntelliJ IDEA not compiling Scala code

While I was fixing the problem with the annotation, I noticed a much more worrying problem, which was that IDEA wasn't compiling my Scala code. Pressing CTRL-F9 (Command-F9, actually) did nothing, even if I changed the code and saved the file and tried again.

Coincidentally, I also noticed at this point that controller was actually spelled 'Conroller'. So I renamed it, and just after I did a little box flashed up saying a Scala file had been detected and did I want to install the Scala facet. I wasn't quick enough to click it the first time, so I had to rename the controller again and hit the 'Create Scala facet' link.

Then I tried to compile again and I was shown a dialog box with the message "Cannot compile Scala files. Please attach a scala-compiler.jar to any project module." Seeing as I'm using Maven, I decided to add the Scala compiler dependency to the POM instead of directly into IntelliJ (which I assumed might remove it on the next POM update anyway):
       <dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-compiler</artifactId>
<version>${scala.version}</version>
<scope>provided</scope>
</dependency>
I don't want to package the Scala compiler into my WAR, so I've used the 'provided' scope because this makes the artefacts available at compile time, but NOT at runtime. Now I compiled in IDEA, and finally I get the same error in IDEA that Maven was giving me earlier, and I fix the annotation on the controller to use an Array:
 @RequestMapping(Array("/hello.html"))



Problem 5: AppTest.testKO fails (even though I deleted it)

After getting IDEA compiling Scala properly, I executed the Maven package goal again and that silly AppTest.testKO caused my build to fail, but I'd deleted the test class! I realised I hadn't run the 'clean' task for a while, so I did that and then it was all building successfully again.

Problem 6: Spring Web requires Commons Logging

When I first tried to start Jetty, I got this error:
2010-01-16 13:59:12.392:WARN::FAILED ContextHandlerCollection@58a1a199: java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
2010-01-16 13:59:12.392:WARN::FAILED HandlerCollection@5b787144: java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
2010-01-16 13:59:12.392:WARN::Error starting handlers
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:179)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
It appears that spring-web requires commons-logging, but doesn't declare it as a dependancy. I solved it by adding this to the POM:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>

Problem 7: DispatcherServlet's Context Configuration File

Having fixed the commons-logging problem, I started Jetty again and got this error:
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/dispatcher-servlet.xml]
Jan 16, 2010 2:01:07 PM org.springframework.web.servlet.FrameworkServlet initServletBean
SEVERE: Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/dispatcher-servlet.xml]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/dispatcher-servlet.xml]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:341)
By default, the DispatcherServlet will look for a config file with the name of the servlet entry ('dispatcher', in my web.xml) with "-servlet.xml" tacked on the end. I got the DispatcherServlet to read my configuration file by adding this to the <servlet> in web.xml:
       <init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/web-context.xml</param-value>
</init-param>

References:
Spring FrameworkServlet javadoc

Problem 8: Scala Syntax for Accessing a Class object at Runtime

When I first wrote the CustomerController.viewCustomer method, I tried to use the Java syntax to access the Customer's corresponding (runtime) class object:
sessionFactory.get(Customer.class, customerId)
which didn't compile. After realising I'd never had to do this before in Scala, I went searching and found that the syntax for getting the class object representing a type at runtime in Scala is:
classOf[Customer]

References:
Scala for accessing a Class at runtime


Problem 9: Hibernate Depends on the javax.transaction / JTA

When I first added Hibernate to the POM, I tried to compile (without adding any Hibernate code) and Maven gave me the following error:
Missing:
----------
1) javax.transaction:jta:jar:1.0.1B

Try downloading the file manually from:
http://java.sun.com/products/jta
Since I was pretty sure that wouldn't be using any JTA features, I simply added an exclusion for it to the <dependency> in the POM:
       <dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.7.ga</version>
<exclusions>
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
</exclusion>
</exclusions>
</dependency>

I should mention that IntelliJ's POM integration here was AWESOME, allowing me to auto-complete the group and artefact IDs of the exclusion by showing me a list of all Hibernate's transitive dependencies! If any IDEA developers are reading this - you guys ROCK!

Problem 10: Spring can't find HttpServletRequest

When I tried to compile the CustomerController for the first time, I received this compilation error:
Error: error while loading View, Missing dependency 'class javax.servlet.http.HttpServletRequest', required by /Users/graham/.m2/repository/org/springframework/org.springframework.web.servlet/3.0.0.RELEASE/org.springframework.web.servlet-3.0.0.RELEASE.jar(org/springframework/web/servlet/View.class)
The problem this time was that spring-web, while relying heavily on the Servlet API, declares the dependency with the 'provided' scope, which is the right thing for the Spring guys to do but a small gotcha for people trying to use it. The solution is just to add a sevlet-api dependency into your own POM (which should ALSO use the 'provided' scope):
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>

References:
Maven Repository: javax.servlet::servlet-api


Problem 11: Incompatible version of SLF4J

After adding the javax.servlet dependency, I started up Jetty again and Spring spewed out the following error along with a massive stack trace:
2010-01-16 21:47:54.804:WARN::Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring-context.xml]: Invocation of init method failed; nested exception is java.lang.IllegalAccessError: tried to access field org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory:
java.lang.IllegalAccessError: tried to access field org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
I found a forum saying that the slf4j-api distribution had a different implementation of StaticLoggerBinder to the one in the slf4j implementation JARs, and that to get it to work you need to include both in your classpath (with the API having priority). The solution was to add the SLF4J API to the POM:
       <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.5.8</version>
</dependency>

References:
StaticLoggerBinder.SINGLETON IllegalAccessError on Hibernate forum

Problem 12: NoSuchMethodError in Hibernate Annotations

I was originally using Hibernate version 3.1.3, as there was some repository indexing page I had browsed suggested that was the latest. When I started up Jetty, I got this error message:
2010-01-16 21:52:06.913:WARN::Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring-context.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.hibernate.cfg.SecondPass.doSecondPass(Ljava/util/Map;)V:
java.lang.NoSuchMethodError: org.hibernate.cfg.SecondPass.doSecondPass(Ljava/util/Map;)V

I found a page where someone had the same problem and a respondent suggested they try a newer version of Hibernate, so I used IntelliJ's Maven integration to download the whole index of repo1.maven.org and then auto-complete the version for the Hibernate dependency, which showed me that the newest version of hibernate-annotaions was actually 3.4.0.ga. Switching to the latest version made the error go away.


Problem 13: Spring Form Binding Requires a Command object

When I first tried to view the newCustomer JSP, Jetty returned an error page showing this:
2010-01-16 21:54:19.068:WARN::/customers/new.html
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
I had, as I often do, forgotten to provide a blank form object for the new form, which was easily solved by adding this method to the CustomerController:
 @ModelAttribute("command")
def createCustomerForFormBinding = new Customer

Problem 14: Can't Access a Scala 'var' from JSP

After providing the blank form object for the JSP to bind from, I got this error:
Invalid property 'name' of bean class [au.com.belmonttechnology.data.Customer]: Bean property 'name' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

I was actually expecting this one to happen! It occurred because a var in a Scala object, while publicly accessible, does not conform to the JavaBeans specification, which is what JSPs and JSTL use to inspect beans and retrieve data from them. Scala provides the @BeanProperty annotation that can be used to tell the compiler to generate getter and setter methods for a variable in order to make it accessible by JavaBeans-reliant tools.
 @BeanProperty
var name: String = null;

References:
JavaBean Properties in Scala


Problem 15:

When I first submitted a request to CustomerController.createNewCustomer, I got the following error:
No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
I remembered that I had decided to experiment and see whether my OpenSessionInViewInterceptor would be automagically picked up by the default annotation handler mappings (some Spring beans do this for some of their dependenices). But, they weren't. Solution: define the mappings bean explicitly and inject the interceptor as a property:
   <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list><ref bean="openSessionInViewInterceptor"/></list>
</property>
</bean>


Problems solved.
Hope you enjoyed that.

Graham.