Welcome to JoshLong.com, home of my personal blog
<< Last | Next >>
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.

August 16, 2009

You're looking at a work in progress..

Man at work

You're looking at a work in progress.

The software that runs this site - joshlong.com - is home-brew. I built it myself, not because I feel like I'm going to do an inherently better job than any of the numerous pre-built options - furthest thing from it, actually.

I built it myself to be able to eat my own dog food. If I had to learn at the same pace I take on a new job and get exposed to a new skill set by force, I'd know much less. Practice is the only thing that can be usefully attributed to improved skills. The previous version of this site was written in Spring MVC so I could refine my understanding of the @MVC model and truly get a feeling for how it works (very nicely, I should add). I've long been a fan of Tapestry and have built numerous sites with it. I figured, with all the new work going on in the JSF world that it was time for me to refresh myself on that platform, especially as JSF 2.0 creeps ever closer.

JSF has seen major "upgrades" (in lieu of actual upgrades from the specification) from JBoss, with Seam, and with the Spring Faces support from SpringSource. Additionally, RichFaces and numerous other projects have evolved their component frameworks so much that result is rarely portable, but usually very nice. In effect these component libraries are their own sort of framework and often carry their own specialized support for core framework concepts like component development, JavaScript, rendering (i.e., view templates), Ajax and internationalization. These frameworks can make JSF very pleasant.

Except... when it isn't. It turns out that JSF's many weaknesses - while in some places well addressed by some of these 3rd party solutions - are not completely surmountable, and in some cases you're forced to simply "grin and bear it." This includes things like statelessness (you'll be greeted with a JESSIONID on your first request, for example), binary responses, and SEO-friendly URLs. I've talked about solutions for some of these problems in Spring MVC before, but they were to augment a capability that was already there. Here, the solutions and the home-brew components I had to put together were to avail myself of these capabilities in the first place.

For SEO-friendly URLs, I found an incredible library called Pretty faces. I'm still using JAWR, as before, but because I'm also using RichFaces - which has its own CSS/JS compression mechanism, the solution's not quite as effective as I would have liked. Still, 2 heavily compressed, minified JS files and CSS files (one from JAWR, one from RichFaces) still beats 10+ HTTP requests on non-minified/non-gzip compressed resources required otherwise!)

The blog software itself has many components, only about 20% of which is the UI layer. Thus, porting to a new UI framework's pretty easy because the back end and most of the processing are divorced from the UI layer.

But... Why?

No good reason, really. I know what you're thinking - "what could possibly be more 'website site babysitting a database' than a blog?". Since I'm trying to experiment with things, I've hit a few different places where it's paid to invest in exploiting temporal decoupling, and thus in investing other technologies. Most of these features are part of the creation of blogs, thus, not something you'll ever notice. There are two ways to create blogs on this site. An administration section in which I can log in and post blogs and save drafts is the sort of first-blush approach. It works well enough, but it's not nearly as full featured as the equivalent functionality inside GMail for composing an email. So, I create a Spring Integration integration that polls an email and posts that. It's got a white-list on incoming e-mail addresses, of course, and I've had to do a few unconventional things to make it work, but it's actually the most fluid way to deal with my blog. Not surprisingly, this feature's available in other blogging software, too.

Once I do send in a blog, processing occurs on the blog entry itself. The act of creating the blog triggers a jBPM process that prepares the blog for final publication. The jBPM process is handled in a separate VM, with JMS serving as the transactional queue that pops tasks off of the queue and handles the work. This is useful because it lets longer running tasks happen with no apparent delay to the readers of the site.

Any externally referenced images in the blog are parsed and their URLs used to asynchronously download the image, which gets stored in managed file system. Then, in the published blog, you see a URL pointing to that managed image, not the original, which means if the original disappears, my blog will still look correct.

Another part of the process involves submitting pings to the various syndicates for a blog to let them know they should update their listing. This too is something that a lot of other blog software will do, but it can take a while which is why in my software it's modeled asynchronously.

The number one reason for building my own blogging solution is, simply, that I can say I did. Because the domain model and services tier are familiar, it's easy to gauge progress with a UI framework by how quickly I'm able to build for it.

Naturally, there are many (seemingly endless) reasons not to do what I've done. However, they all focus on practicality with respect to setting up a blogging solution. They fail as means by which to practice my craft.

Having said that, please excuse any inconsistency in this blog as I'm still tweaking things (as I tend to do every 6 months or so. The software's more or less at parity with where it was in Spring MVC, having ported the UI layer over. Missing are keywords and descriptions in the meta tags, a working version of the admin section (though, as I indicated, I use the e-mail integration more frequently and that still works since it has nothing to do with JSF or servlets), working titles (ie, each post's title should appear between the <title> tags in the browser window, and I'm sure there's more.

There are many fixes in this new software, too, but ideally, you'll never notice them :-)

If you notice anything I'm missing or you think might be worth experimenting with adding in a reasonably malleable blogging platform, leave a comment. Thanks!

July 22, 2009

Composite components in JSF 1.2.x

I'm trying to build a component in JSF that in turn has several drop downs that, with the magic of RichFaces, updates the server on the state via Ajax and rerenders the components "downstream" of the component whose state has changed. This is the classical idiom of a drop down has options depend on the previous selections made. The component's used in several places on the system and it would be magnificent if we could blackbox its internals.

With Tapestry, you could build a component that does its work and then "outjects" or writes a value to a property upon completion. Imagine, for example, a login form. The login form has two text fields (email, password, or anything like that) and a backing class. As the login form component is rendered, you might have preconditions to establish, so you use the Tapestry component life cycle to setup state on the fields before rendering. Finally the text fields are rendered. When the form is submitted the fields values are updated and you have a chance to read the values and perhaps do something with them. For example, if the credentials are correct, you might do a query and create a valid User object. The User object is then set on a property and that property can be bound to a property of the client of the component. If you use the same component 10 times on the same page, they all have their own internal copy of the property and they can all update the same one or they could update 10 individual properties. That is, the "backing bean" is scoped to the component, not the page.

The difference with JSF is that for any kind of composite components you have to do soething like building the tree or using Facelets. These components will in turn require some place to store the values they submit. For the above example of the login form, the user name and the password need some place to be stored. Since facelet ui:components don't have their own backing bean, you need to provide the backing bean for the values. Thus, it's up to the client of the component to provide storage for internal state of the component. Not very component oriented. And, more to the point, it quickly becomes untenable if you want to use the component more than one time in the scope the backing bean lives. That is, you can only use the component once per request or once per session (without creating new backing beans, at least).

I know that JSF 2.0 will feature better support for composite components, but I need this to work on JSF 1.2, and have not managed to find many good resources / examples on how to build a sophisticated UIComponent subclass so it can handle its own storage.

Anybody have any ideas?

July 19, 2009

JoshLong.com on EC2

This is my first working version of the system being posted from the EC2 cloud. Performance seems alright. I'll update as I dig more into the capabilities. So far getting things up and running has been relatively painless. There's something inherently awesome about being able to login and setup your own server without having to beg for certain extra capabilities.

I like most that this could eventually grow with a minimum of fuss.

June 15, 2009

My talk on Spring Integration At TheServerSide.com '09

I did a talk waaay back in March on Spring Integration for TheServerSide Symposium. If you're into Spring and want an hours worth of good wholesome ESB fun, may I humbly suggest you check out the talk. I'd love to know what you think so please feel free to leave a comment!

June 7, 2009

Tapestry 5.1

Recently, I've been playing with Tapestry 5. The experience has been extremely satisfying. Although there are issues that could be worked on, on the whole this is the most pleasant development environment I've ever use for Java Web development. Frankly, it started as just a way to keep my mind away from a main project I'm working on. I figured I'd give it the five minute test. Actually, this is the third time I 've given it the five minute test, and this time it took. What did it was release 5.1, which sports a few features that indicate that Tapestry 5 is becoming a very "practical" choice, not just the right one.

Tapestries 5.1 sports the ability to gzip compress, as well as consolidate, JavaScript files. It does other things with images and css, too. It's not just yet on par with JAWR - which, honestly, I love - because there's something freeing about knowing that if your page needs libraries x, and y, that there's a component out there that's doing everything possible to make the impact of inclusion of that library acceptable. CSS and JavaScript are to the web what "jars" are to the JVM: an encapsulated packaging of externalized, reusable functionality. Being able to optimize loading them, then, is crucial.

Knowing this, I decided to give it a look. I got into it, just a little. I used the Maven Tapestry archetype and created a separate project. Downloaded Tomcat 6 and even loaded Eclipse 3.4. I imported the Maven project using the m2eclipse plug-in, setup a Tomcat 6 server instance, and deployed my application to the instance. I configured Tomcat to "serve modules without publishing," and disable auto publishing. Then I crossed my fingers and hoped for the best. I loaded the browser and hit the front page. The site that's generated is pretty, but boring. It does, however, prove inviting. I returned to Eclipse, associated the HTML editor to *.TML files, and then started hacking. I started with a change to a .TML file. <h1>Hello, world!</h1>, placed in the middle of the Index.tml file. I refreshed. It worked...! I went to the Index class itself, and added

 public String getMyMessage (){
        return "Hello, moto.";
 } 

Then, on the Index.tml file, I added ${myMessage}.

Again, I just refreshed the browser, and it worked! In comparison to Tapestry 3 and 4, this was great. But I've blogged about Zero Turnaround's JavaRebel product and I've certainly seen Tomcat do some neat things with regular Struts projects or Spring MVC projects. I wasn't.. aghast, just yet. Finally, I started getting into it.

I have used the various versions of Tapestry before, so I knew - essentially - what components to expect and essentially what to imagine possible. I had programmer courage. So I was a little more ambitious and decided I'd tackle something a little more ambitious. I started with a component to provide a panel. The panel would have a parameter for a ValidationTracker, which is the object that keeps track of what validations have occurred on a @Form component (very much like ActionErrors/ActionMessages in Struts. The panel would turn red if there were errors in the form it contained. This was a hard thing to do before because Tapestry had issues with the order of the layout of the components.

Suffice it to say, it worked. It was also blissfully simple. No interfaces, not even annotations if I didn't want them. I was able to parameterize the title of the panel using a @Block (like a facet in JSF). In a package adjacent to my test page, I added a simple POJO, with a few accessor / mutators (a Customer class, with the usual sort of properties..). I declared an instance of it on my test page's class and added a @Property annotation to it - I didn't have to even create a java bean style accesor! I added a Form and a few TextField components to the class, too.

@Component (parameters={"value=customer.email"}) private TextField email ;
@Component (parameters={"value=customer.password"})  private TextField password ;
@Component private Form form ;

On my page, the I had:

<form t:id="form">
 <t:label for="email" /> <input t:id="email" /> <br/>
 <t:label for="password" /> <input t:id="password" /> <br/>
 <input t:id="signup" type="submit" />
</form>

This seemed like enough, so I hit refresh and .. unsurprisingly, it worked! Naturally, this doesn't do anything. I wanted to make the Form component do something on successful submission. I looked around, and the simplest way to do that was to name a method as though I was descrbing it in English:

  void onSuccessFromForm ()  {
    System.out.println ( new ReflectionToStringBuilder ( this.customer).toString ()) ;
  }
  

And of course, that worked! It's worth mentioning that during all of this - method additions, field additions, component adjustments, etc, I've not redeployed or published or even waited for more than a split second even once. The 5 minutes had become an hour. The reason I write this blog is because I'm now well into hour 7, and I'm thoroughly impressed. It's actually fun to work in. If you've ever had that wow! moment in a dynamic language where you just can't beleive how nice it is to hit refresh and work, then you'll appreciate Tapestry. I can't usefully compare it to another Java framework because there's nothing like it. It's liberating. Check out Neal Ford's amazing "On the Lame From The Furniture Police" to watch a discussion on keeping focus, flow while working. In it, he basically discusses just how damaging a minute idle time is when developing an application. Tapestry breaks that cycle for you. No more flow stoppages. I've become impatient with the browser's ability to repaint, actually!

I wholely recommend you take a look at Apache Tapestry 5.1.

<< Last | Next >>