Welcome to JoshLong.com, home of my personal blog
November 17, 2009

Understanding Go

Go, a new language from Google, has created quite a stir. It has a great pedigree, owing to renowned experts like Rob Pike (a member of the Unix team, and a creator of the Plan 9 OS from Bell Labs.) The language is a procedural language (like C, or Python) which offers a strongly typed, but flexible type system (not centered around object-oriented facilities as we know them from languages like Java and Ruby). The syntax is a strange mix of C and Python. Honestly, it feels like C when you read it, but it writes more like Python - lots of features in the syntax that are designed to be consistent, predictable.

One blog entry prompted a very lively discussion of the language: it made the comparison that Go seemed awfully similar to Algol 68, a language 40 years past irrelevance. The blog entry said that while Algol 68 was a nice language, Go might be considered an efficient language. It claimed that efficient languages are the ones that - ultimately - propagate. Witness COBOL, C, C++, and Java, for example. Go, thus, may very well be a very efficient language, but it's not even close to a nice language. It's a lost opportunity.

Programming languages tend to come and go, but they all advance basing their innovation in some small part on their predecessors. Programming languages have to evolve slowly. Languages do not exist in a vacuum. They must respect the work that's preceded them, while innovating. They must strike a careful balance, never alienating the existing community, the legacy base, and always advancing the state of the art. Doing so incorrectly can be the biggest sin a language can make. Kowtowing to the legacy of C crippled the evolution of C++, leaving it a confusing mix of phantom requirements and artificial features. Conversely, Java achieved meteoric propagation because it looked and felt like C++ without many of the warts. This made the transition to Java easy. Compatibility is a double edged sword.

Most recent languages look and feel like C/C++. They've innovated ever so slightly, inducting into the syntax features formerly handled by libraries. Or, the language is flexible enough to support requirement-specific DSLs. You can see this with Scala and Groovy, Ruby and C#. They're all fairly familiar, but offer advantages in their grammar over their predecessors. C#, for example, introduced LINQ, while Scala surfaced its concurrency facilities as an Actors DSL. The idea of a language syntax as a differentiators is even more relevant of late. The .NET runtime popularized the idea of a multi-language run time. It meant that choosing a language did not mean forsaking libraries. The JVM has matured, and there are many languages implemented atop it, as well. Other infrastructure VM projects have emerged, like the LLVM.

So, I don't blame Go for looking so much like its predecessors. That's the cost of doing business. It's intended to be a general purpose language, after all. It does have a few unique features surfaced as language constructs, like intrinsic concurrency facilities, which it calls gorountines.

I don't understand why they have built another virtual machine. If Go is going to innovate, it will be in its Virtual Machine. Why not the CLI, JVM, or LLVM? The language has strong support for interop - easily wrapping native code much like you might using C++. The .NET CLI supports this sort of thing, though. I understand the language needed to run on Unix (at the moment, you can't run it on Windows!), and perhaps Mono wasn't sufficiently advanced. Why not the JVM? Would building that kind of infrastructure be that hard? What about the LLVM? It seems well suited to working on Unix and to handling interop. Perhaps interop is not the only concern. The implementation of the goroutines seems to have been a priority. The language does not yet have assertions or exceptions specifically because doing so would be awkward with goroutines. This language, as Mr. Pike explained it, was created for Google to build servers. Cheap, and efficient threading was priority #1. This piques my curiosity. Why could the JVM - which hosts Scala and Clojure - not be used to build goroutines. Is there some fundamental flaw that makes concurrency on the JVM a non starter? I don't understand.

I would agree that the language is not particularly novel. What I don't understand is why the VM is novel. Clearly there are requirements I don't understand, and this is why I think Go will be worth paying attention to, in much the same way Erlang is.

There is also something refreshing about a genuinely new language. New platform, new libraries, new syntax. Programs written in a language like that represent advances. Shortly after the debut of the language, a command line Twitter client emerged. The example is promising - by definition the implementation was from-scratch. It was quick, and the result is imminently readable.

Perhaps I'm over thinking this. Perhaps the language will be successful because it's simple, and efficient. Perhaps the VM is some how unique and better served by a custom implementation. Only time will tell.

November 12, 2009

The Last 2 Crazy Months

What a busy couple of months!

I started last month (from October 2nd to the 11th) at the Java2Days conference in Sofia, Bulgaria. I gave three talks on Spring and JSF, Spring and jBPM, and Spring Integration (the Spring ESB-like framework). I think the slides will be available there in shortly. Meanwhile, here are some photos of the event below, though you're encouraged to log in to Facebook and check out the full galeries there.

The name of the gentleman on the far left escapes me, but that's John Lewis, Emo, and yours truly on the right

From left to right: Ivo Penev, Gisele Consoline, Rob Harrop, yours truly, John Willis, and Heath Kesler

I had a great time at the conference. The audience was great the discussions great, too. The drinking was good, too! :-)

At some point, I got some sort of stomach bug (perhaps in Greece?) and when I returned home, I was severely dehyrdated. I spent a little time hooked up to an IV and then spent the subsequent week pounding antibiotics, gatorade, and soup. There's a thousand ways to get sick, only one way to get better!

After that, I got deep into the final edits for my book "Spring Enterprise Recipes." Really enjoyed that process - it's fascinating to see what goes into writing a book. Trust me, the book is far better for the effort of the amazing editors at Apress! :-)

I spoke at the Pasadena Java User Group on using Spring Integration - that crowd was very cool and the discussion that ensued was also good.

Recently, my sister got married. I wish her, and her husband, many happy days together.

I think that wraps up the highlights. I'll start chiming in more frequently. A lot has happened of late, including the debut of Google's Go programming language, The Motorola Droid, the continued standoff between Sun/Oracle and the European Union over objections to Oracle's accquisition of MySQL, and more. Exciting times...

September 10, 2009

CRUD's Not The Answer

I was really glad to see Udi Dahan's, "Don't Delete. Just Don't." I wholely agree with the main premise - that deletion is rarely, if ever, a valid business state and that care should be taken in dealing with it. He cites various examples, saying, "The real world doesn't cascade." His example is of a marketing department that deletes an item from the catalog. Should all orders containing that item then be unlinked? Should they redo the company's profit and loss statments?

His example's a perfect illustration of a valid case where care needs to be taken both in modeling the case and dealing with it in code. I fear a lot of people have gotten hooked on instant-models or CRUD "frameworks." The idea that you can annotate a few entity classes and suddenly you have a model and business logic all taken care. A lot of this became popular with Ruby on Rails and has only gotten worse in the JEE world. It's now common to expose EntityManagers to the web tier (both the Seam and Spring Web Flow examples, not to mentino the Open Session in View pattern itself, speak to this) and to let web frameworks handle the lifecycle of entities and committing transactions on that EntityManager to persist those entities. We now think of record creation and managment as so mundane that we've automated it and surrounded it in scaffolding.

Unfortuntately, this misses the true value. Objects in a system have state that has dependencies. Just because an entity has a (required) no-args constructor, it doesn't mean that you should not write a constructor with dependencies. A lot of this stems from the "active objects" or "naked objects" pattern, where objects are open books whose state can be mutated on the UI tier directly and those changes propagated directly. We tell ourselves that we can apply Hibernate validations (or validations in any other ORM framework) and that we'll guarantee valid business constraints thus, but it rarely works out that way. Prescribing the valid creation and destruction of an object is critical.

The most insidious part of this abuse is that it rarely ever occurs in the first iterations of a project, only in maintenance. People "forget" how an object is created, or destroyed. They forget details. Consistancy with other parts of the system is forsaken because, after all, how much could there be to it? This happens more often than you'd expect: new people come on to the team and are assigned to rework an existing feature and screen in a system. Institutional knowledge is important but it's not always easily transferred, so safe-guards need to be taken.

Plus, as business evolves, object creation is often only part and parcel with a larger process. If a new customer is added to a database, and nobody does anything with it, did it really get added? Put another way: if a new customer gets added to a database, there's an implied lifecycle that customer must follow. Perhaps a trial period window and then a follow up email? Perhaps a monthly subscriptio fee? Who knows, but the act of instantiating a Customer object and then issuing entityManager.persist( customer ) will rarely, if ever, be enough.

Indeed, I've seen many projects build their models using only a GenericDao<T> variant. This is dangerous. Transitions from one state to another for an entity can often cost money.

Do things the old fashioned way, building services that handle the business operations, not merely Create, Read,Update and Delete objects. Using Dao's in a view tier is almost as ghastly a sin as making JDBC calls from the view, and encourages the same kind of copy-n-paste code reuse we prided ourselves on having moved away from.

While the services approach isn't exactly code-generation friendly, it can pay off in the long run. As soon as you decide to use your services in a phsically separated tier, you'll be glad. It's easier to build services that express every dependency as a method parameter. There are several reasons why this works out. While web service support is getting better, object marshalling is still the number one headache. Most toolkits make interoping with primitives a brease, though. It may seem like your losing ground by not taking advantage of the POJO you have floating around in the view tier, but in point of fact it's rarely that big a burden to unmarshal the relevant fields and use those instead. On the services side, reloading the relevant record is painless because the entity's usually cached and thus refetching it is cheap.

Take for example the idea of a shopping cart which surfaces methods for adding line items to orders, orders to shopping carts and shopping carts to customers. A clean version of this might look like:

 
 public interface ShoppingCartService { 
     ShoppingCart createShoppingCartForCustomer( long customerId, 
                                                 Date 
whenShoppingSessionStarted ) ; 
     Order createOrderForShoppingCart( long shoppingCart ) ; 
     LineItem createLineItemForOrder( long orderId, long productId, 
int quantity) ; 
     void removeLineItemFromOrder( long orderId, long lineItem ) ; 
     void startOrderFulfillment( long orderId ) ; 
     /*  other methods for loading and removing the various 
         objects, as appropriate 
     */ 
  } 

In these methods, you can do sanity checks, care for business cases, handle the state of the various objects and not worry about having a transactional resource like an EntityManager or Hibernate Session open in the client thread. In this example, you might imagine the Order won't officially be fulfilled until it's paid for, at which point it'll move to the PAID state. Simialarly, adding a LineItem might require a check to an inventory, decrementing how many of those Products are in stock. The same is true of the inverse operation: removeLineItemFromOrder should appropriately restore the inventory count and update the totalPrice field on the Order.

This requires one interface method declaration's work more than if you had simply obtained the EntityManager from your Seam backing bean and executed the logic there, except now the logic's codified and reusable.

September 3, 2009

Setting Up jBPM 4's XSD File In Eclipse

I've recently been playing with jBPM 4.1 and, while I haven't quite gotten into it, I did manage to break an Eclipse setup of my "old" jBPM 4.0 code. This is definitely a user error. So, trying to ensure I have a reproduciable baseline, I start setting everything up again (I don't have the jBPM plugins or anything installed -- I keep it mean and lean, if possible. )

I got to the point where everything was running fine again from the IDE, but I noticed I no longer had code completion for my jBPM .XSD file. I'm not sure if I ever did, or if I did, then I've forgotten how. So, I stumbled through getting it working with the Eclipse Resource Catalog. Here are the steps to reproducing it if you have the same issue.

  1. You'll need a copy of the .XSD itself. For me, the simplest option was to just download the source jar and use the XSD file therein.
    mkdir ~/xsds; cd ~/xsds ; 
    wget http://repository.jboss.com/maven2/org/jbpm/jbpm4/jbpm-api/4.0/jbpm-api-4.0-sources.jar 
    ; 
    jar xvf jbpm-api-4.0-sources.jar ; 
    
  2. In Eclipse, go to Window > Preferences
  3. Search for "XML Catalog," under the "XML" node.
  4. Click "Add..."
  5. Fill out the dialog, using the values below.

I hope this spares somebody some pain. Once you've got it working, go check out the awesome new jBPM 4.1!

August 29, 2009

My Christmas Wish, OR How the JVM Will Outlive the Cockroach, and .NET

It started with a Tweet from Miguel De Icaza. Miguel's the leader of the Mono project, whose goal's to bring .NET to Linux. He's also the former leader of the Gnome project. Generally, he's whip smart and not usually prone to flame baits. So, I tend to read his words carefully, as it usually pays off. He said: "I wish Java tried to compete with .NET, but they seemed to have given up a long time ago: http://tinyurl.com/mfxmqm"

At this point I wanted to write him a terse letter stating my point of view, stating how he had clearly missed the obvious. I resisted, hugged the wife, cried a little, sat on the beach with candles, attended a book club meeting, found Jesus, and then came back and reconciled that I was just sad because he was right. He was also pointing out the obvious. (There, at least I can say that! in the anonymity of my blog, far, far away from where he might see it...)

The link points to integrations in Project Coin, a project that's taken the JDK and aggressivey evolved the language to try certain features out in an isolated fork. In general, I'm supportive of the movement, but it's a sad truth that any final edition of JDK 7 is already late, and will likely not incorporate many of those integrations in Project Coin, or even many of the originally announced - big ticket changes coming straight from Sun. JDK7 is the Windows Vista/Longhorn of the JDKs.

You remember Longhorn, right? It was the code name for Windows Vista for a few years. If I recall, there was talk of integrating 4 pillars or waves of technology into the then-hyped next generation of Windows, including WinFS (Am I wrong in thinking that it was called something else, then? Avalon? Or am I thinking of the now-defunct Java DI container?) Indigo, and a slew of others. As the roadmap slipped further and further, more things were dropped. In fairness, in 2009, some of those pillars have subsequently shipped, sort of, as parts of .NET 3.0-3.5x. Some are lost to the annals of history.

With a heavy heart I proceeded to code, ignoring what he said. I'm tougher than that. I can handle having the rug yanked out from under me. "Why would he say that about my precious Java??" I thought, typing as I thought it. "I wish I could come up with something to refute his claims!", I moaned. Something elegant, quick, crazy fast, and future proof. Something's got the best of C#, F#, Python, JavaScript and more. I tend to ignore skills I've built up over years of use and revert to primitive, conveniently blog-friendly samples from tutorials when I'm stressed (don't you?). And boy was I stressed! I looked at my screen. I was really in a tizzy at this point, thrashing away at the keyboard! (Like in those movies where they feature somebody running their hands along the home row and suddenly they've infiltrated the FBI's secret-most files.)

Here's what I had typed:

object Maps { 
 val colors = Map("red" -> 0xFF0000, 
 "turquoise" -> 0x00FFFF, 
 "black" -> 0x000000, 
 "orange" -> 0xFF8040, 
 "brown" -> 0x804000) 
 def main(args: Array[String]) { 
 for (name <- args) println( 
 colors.get(name) match { 
 case Some(code) => 
 name + " has code: " + code 
 case None => 
 "Unknown color: " + name 
 } 
 ) 
 } 
} 

It was a Christmas miracle! A language on the JVM that already had most of the proposed changes in Project Coin and great deal otherwise and was very fast and that worked on all platforms, just like Mono! Errr... that is, just like Java!

This language, Scala, has gained a great deal of traction in the Java community and even people you'd expect to offer otherwise have endorsed it. People like James Strachan, creator of Groovy, and James Gosling, creator of Java.

I just hope that other people can find out about this wonderful language. Why, wouldn't it be nice if -for Java 8 (will we ever get to have a Java X? How cool would that be??) - we just shipped Scala?

And that, boys and girls, is how Java outlived the cockroach, in our hearts.

The End!

August 27, 2009

A Survival Guide to Maven, OR, Why Maven's Still Cool

The Problem: Confusion

I've had a lot of small discussions recently with people where they were just absolutely not interested in using Maven. Has it somehow gotten a bad reputation when I wasn't looking? Am I missing something? When did I suddenly become the guy using a tool that was too slow, or not agile enough for everybody? I can still sing and dance and jump like you guys, too! Even if I do use Maven...

So, let old Josh tell you a little bit about Maven. Maybe we're not all talking about the same thing. Consider this a survival guide to Maven.

Maven, like this guide, assumes you're trying to solve the 80% cases effectively. Already, we have a point of confusion!

I'm pretty confident that your first thoughts on that last sentence were to what Maven considers "80%," and you're probably wondering what you might reasonably call Ant's "80%" cases. I would argue that Maven's "80%" is 80% of a much, much bigger pie.

I haven't met an Ant build yet that couldn't be cut down in complexity by using Maven. Sure, sometimes the resulting Maven pom.xml was more verbose (though, that doesn't happen all that often in practice, either), but that's not the same as complexity. Intrinsic complexity is one thing. Surface complexity is another. I define intrinsic complexity as the concepts required to effectively deal with a problem in a problem space. I define apparent complexity as the busy work a process presents you with to obtain a goal.

I'm pretty convinced Ant suffers from both of those kinds of complexities. I wasn't going to start any bar fights about it, but I was pretty sure. Then, Ruby On Rails debuted and made code generation popular again. It brought "convention over configuration" to the mainstream. Then, I knew I was on to something with Maven.

I might argue that when you download Ant and decide to keep it in your tool chain, you think of it as providing a solution, assuming you've configured it, to:

  1. compiling Java source files into classes
  2. copying resources to the right place, such as .XML files, .properties files, etc.
  3. generating .jar or .war artifacts from the aforementioned classes.
  4. generating JavaDocs. I'm adding this one as a "maybe." Does anybody still do this and actually keep JavaDocs floating around? Is the Eclipse or IntelliJ support for rendering in-popup the contents of the JavaDoc not enough?

The enlightened Ant user will also, maybe, add dependency management with Ivy to Ant's 80% cases. I mention this to be fair, though I highly doubt it's that common. I suspect that a lot of Ant users would still relegate that to the fringe 20% cases.

Alright, so we have our 80%. Most people have a sample ant build.xml that they've lugged around and, when it's time to seed a new project, they plop it into place and it's got some variables that need to be replaced and then it does most of the things above. Except JavaDocs and Ivy. I'd be surprised, anyway.

Maven's got all of those features - right out of the box - in 5 lines of XML and a standard directory structure. This is where it stops being a fair fight. No matter how much you tug or pull against that list above, chances are you're at least going to use Ant to compile. No way around it. Even the simplest Ant configuration requires more exertion to acheive that than Maven does. This point, and this point alone, is why I'm just not convinced people are taking a look at this and understanding it. If the goal is simplicity, then there's nothing simpler than nothing. If you've had to put even a moment's care into that list above, than you've already wasted time and could have been using Maven.

Now that I've gotten the soap-box speech out of the way, read on to understand a little bit about it, including how to set it up to do all the things in that list (and hundreds of other things) with a few directories and a 5-6 line XML file (the 5-6 lines comes from my formatting. It could easily be 3 lines of XML, if we're honest.

Things To Know

Where Can I get Maven? Maven is freely available, just like Ant, from Apache. Alternatively, many distributions have it in their repositories. For Ubuntu, it's

sudo apt-get install maven2
This version, as with all repository packages, is slightly out of date. But, at least you're off and running.

How Do I Install Maven? The simplest way is, like Ant, to unzip it, and add the bin folder of the directory to your system's PATH variable. Alternatively, skip to the next question and simply use your operating system's repository to install it, if possible.

How Do I Build a Maven Project Building a Maven project is easy, as the command never changes.

mvn 
install
This is true whether it's your project or somebody elses. It's predictable, and consistant. To use it, ascend to the highest directory in the directory tree that contains a pom.xml file. That's usually the parent project. Usually, Maven projects cascade downwards, so you might try issuing:
mvn install
This will generate a target directory in each project (if there are any). Inspect the target directory for your .jar or .war, or whatever you're expecting. If for some reason there's no target directory in the directory that contains the source code you're trying to build, descend into it to the point where you're adjacent to the pom.xml. Then, issue again:
mvn 
install

How Do I Bootstrap a New Maven Project The simplest setup requires the creation of directories as well as one XML file. But, you'd likely create these directories and at least one XML file with Ant, too.

Run the following on the command line. NB: I haven't translated for Windows. I'm sure it's easy enough, there, too.

mkdir -p 
myproject/src/{main,test}/{java,resources}
You can change myproject to whatever you want. This will create a directory structure like the following:
jlong@studio:~/Desktop/myproject$ find . 
. 
./src 
./src/main 
./src/main/resources 
./src/main/java 
./src/test 
./src/test/resources 
./src/test/java 
If you're just getting started and aren't test-driven, then you can ignore src/test/*. That leaves you with src/main/{resources,java}. Java code goes in src/main/java. Things you'd like on the classpath of the same artifact, such as Spring application contexts, go in src/main/resources.

Finally, you're going to need an XML POM file. POM standards for "Project Object Model," I think. It's the sole center for configuration related to your project. No need to do includes, or externalized configuration or anything. The simplest pom.xml looks like:

<project xmlns="http://maven.apache.org/POM/4.0.0" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd"> 
 <modelVersion>4.0.0</modelVersion> 
 <groupId>com.yourproject.crm</groupId> 
 <artifactId>utilities</artifactId> 
 <version>1.0-SNAPSHOT</version> 
</project> 
You can copy and paste that into a file called pom.xml, at the root of the myproject folder created above. You're done.

From here, so long as you're just planning on using the JDK, etc, then this will work fine.

What do those directories and 5 lines of XML buy me? Think of that as being equivalent to hundreds of Ant targets. The project already has enough information to, among other things:

  1. Generate javadocs: mvn javadoc:javadoc
  2. Compile classes: mvn compile
  3. Compile and generate an artifact (a .jar, in this case): mvn install
  4. Generate a Checkstyle report: mvn checkstyle:checkstyle
  5. Or, in the alternative (and perhaps a complement): generate a PMD report: mvn pmd:pmd
  6. Build a web site with documentation on the structure of the project (anemic thing that it is): mvn site
  7. Build a cross reference of the project's sources: mvn jxr:jxr
  8. Setup project files for your favorite IDEs: mvn eclipse:eclipse, or mvn idea:idea (NB: if you're using IntelliJ IDEA 7 or later, or Eclipse with the fabulous m2Eclipse plugin, then you don't need these plugins. You can simply 'open' the project as you would any project by importing or opening the pom.xml. Netbeans also has incredible support for opening Maven projects directly.

How Do I Add JARs to the ClassPath? Short answer: you don't. You let Maven handle it for you. If you need a .jar, more than likely, it's already available in some repository, in the same way that a package might be provisioned by an operating system (such as Windows Update on Windows, apt on Debian distributions, rpm on RedHat distributions, port on OSX, etc..). For Maven, using a depdendency is as simple as identifying it and adding the metadata to the pom.xml.

There are many ways to "find" a .jar. The simplest is to start browsing a central repository and opening the pom.xml files. To add a dependency, you need it's <artifactId>, its <version>, and its <groupId>. These elements are usually at the top of all pom.xmls. To add a dependency on the Apache Commons Lang library to our project above, add the following lines to your pom.xml, right before the closing <project> element:

<dependencies> <!-- plenty of room to add 
dependencies --></dependencies>
Inside the dependencies section, you will add all your dependency information. The information you enter could be that for a third party .jar, or a .jar in your own project. Perhaps one team's project depends on another's. If Maven can't find the cached version of the .jar, it'll download it for you.
 <dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.4</version></dependency> 

To test, simply rebuild it as before: mvn install. Most of the IDE integrations will have suport for updating the project configuration in the IDE (i.e., the classpath) according to what's in Maven's configuration. If you'd rather not spelunk through the ibiblio repository site, you can always use one of the many Maven repository indexes. A good one is Maven Search. Type in a fragment of what you're looking for and it'll provide you with matches. Thus: I entered "commons-lang" and it found results. Additionally, most of the IDE's will have support for some form of repository browsing.

I'm Test Driven! This one's easy. If you do want to use JUnit (or TestNG), then fret not - that's Maven's default M.O.! By default, any JUnit classes put into the src/test/java folder will be compiled and run before proceeding with the build.

The Tour's Over, What Did You Think?

In this guide, I've given a walk through to the questions I can imagine thinking about when setting up a project with Ant. The result is that you can get a LONG ways with nothing (the minimal pom.xml).

The balance of a given effort is the 20% stuff. As they say, the 20% cases can take 80% of the time. I can't speak to whether this is true or not as Maven's never delayed me, for any particular length, except when I was pushing it to do stuff that nothing else, including Ant, could have done. Even so, if you hit the 20% cases, you can rest easy in the knowledge that Maven is built to be flexible and extendable. It's whole model is exposed as a lifecycle. If you want to inject custom logic at a custom point, doing so is easy. It's also insanely interoperable. In fact, even if you don't want to use Maven but wan't to get a very high quality build script, setup the project using Maven and then use mvn ant:ant. It'll generate an ant script that'll handle most things you'd want to do. Finally, if you decide you absolutely can't live without, or translate effectively, an Ant script, there's good support for running Ant scriptlets inside of Maven.

Go ahead and give it a try if you haven't tried it before or if you were put off. It's truly powerful. The most visible testament to this are the ideas (like Ivy) that are inspired by it in Ant.

August 24, 2009

Building Servlets With Spring

The Problem

Earlier, I wrote about having to build a solution using servlets to write out the contents of the RSS feed for my blog. I am using JSF on this site. There are solutions - like Pretty Faces - that work and provide a lot of flexibility for mouting JSF logic at a given URL. So, initially, my RSS and Atom feeds were being handled by a backing bean in JSF. Being JSF, this necessitated the need for a session cookie (even though, clearly, the RSS / Atom feeds are stateless.)

The cookie wouldn't have been so bad, except that - I think as a consequence - RSS readers consuming the blog were being constantly refreshed for the entire contents of the feed, because to them the resultant blog requested was "different" than the previous version.

The Solution

So, I planned to write a servlet that handled the requests and I expose that in my JSF application. This would be a clear differentiator between the new Spring + JSF version of the software running my blog and the old Spring MVC version: it's uselessly difficult to support stateless endpoints with JSF, where as it's as natural a goal as anything in Spring MVC.

Using a servlet meant I'd lose two advantages I'd had in the JSF application with Pretty Faces: bookmarkable URLs, and the convenient programming environment that Spring Faces afforded me, namely, configuration, dependency injection, etc.

Refinements

I decided to use URLRewrite to solve the boomkarkable URLs (yes, that means this site is hosting not one, but two solutions for bookmarkable URLs in the same .war!) and Spring's under appreciated HttpRequestHandler.

HttpRequestHandler is an interface that, when implemented, becomes serviceable by a Spring framework servlet. The interface looks like:

 
package org.springframework.web; 

public interface HttpRequestHandler {
void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}

You then configure a Spring framework class (org.springframework.web.context.support.HttpRequestHandlerServlet) in your web.xml and name the servlet the same as the bean that implements the HttpRequestHandler interface is named in your Spring application context. By virtue of the fact that your HttpRequestHandler bean is a Spring component, you get all the advantages of using Spring or Spring MVC, without having to load an entire framework.

For my code, the implementation looks something like the following:

package com.joshlong.blawg.site.view.servlets; 

import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List;
import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.HttpRequestHandler;
import com.joshlong.blawg.BlogService; import com.joshlong.blawg.model.Blog; import com.joshlong.blawg.site.view.util.RssFeedCreationUtils; import com.joshlong.blawg.utils.LoggingUtils;
import com.sun.syndication.feed.synd.SyndEntry; import com.sun.syndication.feed.synd.SyndFeed; import com.sun.syndication.io.SyndFeedOutput;
@Component("feed") public class BlogFeedServlet implements HttpRequestHandler { static private String FEED_TYPE_VARIABLE = "feedType"; static private int START_FEED = 0, STOP_FEED = 500;
@Autowired private RssFeedCreationUtils rssFeedCreationUtils;
@Autowired private BlogService blogService;
@Autowired private LoggingUtils loggingUtils;
private SyndFeed buildEntryList(HttpServletRequest req, HttpServletResponse res, String type, int start, int length) { SyndFeed feed = ... // build up the SyndFeed however you want return feed; }
private void showAllAtomBlogs(HttpServletRequest request, HttpServletResponse response) throws Throwable { SyndFeed feed = buildEntryList(request, response, "atom_0.3", START_FEED, STOP_FEED); response.setContentType("text/xml"); SyndFeedOutput syndFeedOutput = new SyndFeedOutput(); syndFeedOutput.output(feed, response.getWriter()); }
private void showAllRssBlogs(HttpServletRequest request, HttpServletResponse response) throws Throwable { SyndFeed feed = buildEntryList(request, response, "rss_2.0", START_FEED, STOP_FEED); response.setContentType("text/xml"); SyndFeedOutput syndFeedOutput = new SyndFeedOutput(); syndFeedOutput.output(feed, response.getWriter()); }
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { String feedType = StringUtils.defaultString(request.getParameter(FEED_TYPE_VARIABLE)); if (StringUtils.isEmpty(feedType)) feedType = "rss"; if (feedType.equalsIgnoreCase("rss")) showAllRssBlogs(request, response); else showAllAtomBlogs(request, response); } catch (Throwable th) { loggingUtils.log(ExceptionUtils.getFullStackTrace(th)); } } }

Thus, it's simpler than a standard Spring MVC controller or a struts controller (though admittedly lacking a lot of the frills - this happens to be a simple use case.

I then configured the web.xml for all of this:

 
   <servlet> 
       <servlet-name>feed</servlet-name> 
       <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class> 
   </servlet>
<servlet-mapping> <servlet-name>feed</servlet-name> <url-pattern>/urlPatternForFeedServlet</url-pattern> </servlet-mapping>

Note that we've used the name fo the bean (configured using bean classpath scanning, so the name is in the @Component stereotype at the top of the class - "feed".) for the servlet name. Sure, it smells a bit like engineered coincadence, but it works well.

From here, all that remained was configuring a URLRewrite rule to map the servlet to the endpoints visible on the site right now ("/jl/entries/blog.atom", and "/jl/entries/blog.rss")

Hope this helps somebody...

August 22, 2009

Quick Update to RSS

I just published a change to the code that should hopefully prevent readers (like Google Reader) from constantly requeuing all my old blog entries as "unread." �I don't know if it'll work (I've never had to debug this particular web client!), but we'll see.

I suspect the issue is something like the following: the spider hits the page which in turn causes it to get a cookie from Java Server Faces, which makes the blog feed look "new." I've checked the last modified dates and so on using Http Live Headers and the Last-Modified dates and everything look alright. Anyway, I'll post back with results once they manifest (or, hopefully, don't manifest!)

Succinctly, the change involved creating a servlet (sort of) and using that to write/render (I wanted to say "feed") the feed.

August 20, 2009

Component Oriented Architectures

Warning, this blog entry is as much a rant as a blog, and tends on the somewhat lengthy side. You've been warned. I'm looking for the secret of life, as always, and failing it, I'll settle for the secrets of software. This is a blog I don't know how to write, but have wanted to, for a long time. I suspect getting it out on paper will let me revisit with more clarity later.

Prompted by Brian Sam-Bodden's musing on the subject a week or so ago on Twitter, I've been ruminating on the notion of a "component." I think that the evolutions of modern day software development are embodied in the notion of a component, not a "service," or a "bean," or anything else. Those words don't convey enough.

Thinking about it, a "component" can be broadly defined as a thing which integrates readily into a bigger thing - that is, it's adapted to the thing that uses it, and any other such thing could be made to follow suit, with the same adaptations. The container is composed of components.

Getting more specific, we think about a component in software as a thing that is integrated into a container and that can only function as a subordinate entity to the container. In practice, this vague description manifests itself as class that implements an well-known interface. Sometimes, being a component means is simply a matter of letting the container control when the component starts working and when it is stopped. Here, you might not even need to implement an interface since object creation and destruction or (typically!) built into the language itself, and thus there's no need to codify it further.

This ends up quite often being too much of an abstraction. Something that is everything is also nothing. So, again, in practice it's a matter of establishing a common interface. In recent years, the "interface" for a component has evolved beyond the literal notion of a language interface and can be any number of things now. After all, all the interface does is distinguish an object as being a component in a sea of non-components. Such a distinction can otherwise be made, as with annotations or attributes in the Java and .NET platforms, respectively.

So, a component is something that belongs to a container and that so marks itself as usable in that container with an interface or some other distinguishing feature.

Now, when the component is deployed, it sustains some sort of behavior, perhaps over a period of time. There is often a setup phase and a destruction phase. This implies a lifecycle, to setup state to begin servicing requests and to stop servicing requests. This lifecycle might provide hooks tot he component unique the containing environment.

Because the component exists inside of a container, collisions are apt to occur. Language features like assemblies or packages help isolate a component, but often the container will provide addressing to further isolate a component from its siblings.

At this point, I think, the nuances are what qualify the application of a component. If we agree on the previous points applying to most components, then surely we agree that following aspects apply only to some components. The specification is where the term component is starts being prefixed, i.e., "web component," "service component," etc.

Analyzing these definitions, a HUGE number of things could be consider a component.

  1. the now-defunct Avalon framework had "components"
  2. Spring has a @Component stereotype that marks beans as "components"
  3. JCDI - the pending DI component model in JEE6 describes "components"
  4. Indeed, EJB's original documentation spoke of EJB "beans," which you might argue was Sun's jargon for "component."
  5. The web frameworks Tapestry, Wicket, Echo, etc, provide components for the user.
  6. The Java UI model, Swing, provides components
  7. The J2ME and Android mobile phone platforms provide "components"

The list goes on and on, but you can see plainly that the idea of a "component" is not new. A component by any other name...

These various notions of a component - though not all of them - share several more concepts which we might describe as key to any description of a component.

Most of them provide some way to export state. In Tapestry, Seam and JCDI, you can "outject" values, effectively binding an internal value to a client's state, so that the internal state is reflected in the external variable when state inside the component changes. This is often called just "binding," and is -usually -an abbreviated way of responding to some event and then synchronizing client state with the state of the component manually. JavaBeans themselves, a core tenant of the Java platform, provides this notion of properties, which are nothing more than accessor/mutator pairs by which state may be shared in a generic fashion. The Dojo JavaScript framework, Wicket, Echo, and Spring, ASP.NET, and Swing all provide support for broadcasting state changes as events. This tends to be very effective as it decouples the listeners from the component itself.

In this discussion I've lumped both events and properties as goals by which to achieve the same thing, and though these concepts are not present everywhere, they're key for good components in this author's experience.

In this respect, Delphi, C# and Scala and other languages that embrace these concepts and codify events and properties have the edge. Software development can't be about being able to bundle state and functionality, it has to be about components that play nicely with each other, not in a box but in an ocean. Promoting the ideas behind a component promotes decoupled, and well behaved, software.

Indeed, the trends in software development themselves beg for components. Grids, with many concurrences and actors at play, are very well suited to components -services exposed behind a publish/subscribe mechanism. Services so exposed publish functionality that other actors in the system can consume if they can address them. This sort of dynamism is already alive and well in things like Jini or GridGain. The components themselves comply with a life-cycle for their respective containers.

The very idea of a component - things out of which something bigger is composed - implies composition. The biggest thing to come out of SOA is the push towards service reuse and composition, which components encourage.

Clearly, I'm thinking this through as I write it, and so any input's appreciated (good, bad, or indifferent.)

The addressability part is key. Brian mentions the notion of a REST-ful component. In the specific, he was talking about a component on a page amight be addressable, but the question is equally well put to how to expose distributed components uniformally.

Is there an ideal way to build components and to model these concepts - what's the next generation of software going to bring us? Clearly, functional languages are here to stay, but they don't preclude the idea of a component, in fact I imagine it might work for it.

What do you think? What's the most succinct way to model software? Is your architecture composed of objects and services? Of global variables and functions? Or of components? What will the architectures of tomorrow look like?

August 17, 2009

Ooops!

Today started off nice enough... I went to Malibu Seafood today and enjoyed a lovely day on the beach and came back to check my blogs and, blam! mistake-in-the-face!

In my last blog I discussed that I'd updated the software powering this blog, and that there might be some bugs to work out.

Boy, am was I on the money on that one! Turns out, I updated the logic used to implement my RSS feed and Atom feed (eh, mainly, the switch - I'm embarrassed to admit - was to actually use the token that ROME expects to generate an Atom feed instead of the RSS 2.0 type of feed.) Bluntly: if you subscribed to my Atom feed, you only got an RSS feed, because I fat fingered the 'feedType' parameter on that one!

Apologies to all those were spammed this morning with 'duplicate' (essentially) blog entries! Everything except this and the one before it are old and can be marked as read... thanks.