Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Friday, August 29, 2008

Id conflict inside Web Browser

Just spent many minutes on a wild goose chase and the underlying cause was that I had a <div> and a <textarea> that shared the same id. $(id) returned the <div>, most likely because it occured first in the document. I then got an error because <div> doesn't response to activate() ... that's a Prototype method attached to form elements.

I would be tempted to make Tapestry enforce this (that the id attribute for any node was unique), but that won't proof it against partial renders under Ajax, so I don't know that there's any point.

What's really going on is that CSS rules based on element id rather than element class are evil, and should only be used as a last resort. The free CSS template I got off the web uses too many explicit ids where it could be using CSS classes. You get what you pay for.

Tuesday, August 26, 2008

Tapestry Europe Tour

I'm going to be in Oslo, Norway for JavaZone from Sep. 16 to Sep. 19th. I'm presenting on Thursday afternoon.

Next up, a week of Tapestry training in London.

I then fly to Amsterdam on Sep. 27th, for three more days of Tapestry training and then some vacation.

Next, down to Paris just for vacation before returning home on October 10th.

Should be a lot of fun, and a chance to meet with new and future Tapestry users. I can't wait!

Tapestry 5 IoC: Binding and Building Services

Tapestry 5 includes its own internal Inversion of Control container. This is often a point of contention ... why not just use Spring or (in more recent conversations) Guice?

That's a complex question; simply put, Tapestry has requirements as a framework that the other containers don't offer solutions to.

This posting is a simple introduction to the basics of Tapestry 5 IoC. In later postings, we'll get into more detail about the advanced features of Tapestry's IoC container, the ones that really distance it from Spring and Guice.

Tapestry uses the term "service" for the primary objects that it manages for you. Spring uses the term "bean". A service is normally an interface and a class that implements the interface. In the most typical case, only a single service implements the interface, but T5 IoC is fully capable of handling the case where one service interface has a number of distinct services; even the case where a single class is instantiated with a different configuration.

Every service has a unique id string. In most cases, this is just the simple name of the service interface. When the same interface is used by multiple services, you will have to identify the service id explicitly.

To keep things real, I'll use actual, though abbreviated, examples from Tapestry's code base.

T5 IoC uses module classes to identify what services are available. A module class is a POJO class with a special method on it, a method named bind(). A Tapestry application will consist of a number of modules: some modules provided by Tapestry itself, some by third party libraries or extensions, and some by the application itself. Tapestry mixes and matches all of this information, all of the services defined by each of the modules, into a single registry of services.

That may sound more complex than it really is. The reality is that in the bind() method, we simply match service interfaces to corresponding implementations:

public final class TapestryModule
{
    public static void bind(ServiceBinder binder)
    {
        binder.bind(ClasspathAssetAliasManager.class, ClasspathAssetAliasManagerImpl.class);
        binder.bind(PersistentLocale.class, PersistentLocaleImpl.class);
        binder.bind(ApplicationStateManager.class, ApplicationStateManagerImpl.class);
        // ... and so on
    }
}

The ServiceBinder is uses generics to ensure that the class you specify implements the service interface. The API is a fluent interface: you can chain a few extra method calls onto bind() to override defaults, for example:

      binder.bind(ObjectProvider.class, AssetObjectProvider.class).withId("AssetObjectProvider");

TapestryModule actually defines quite a few additional services.

Let's look at an example:

public interface PersistentLocale
{
    void set(Locale locale);

    Locale get();

    boolean isSet();
}

I've stripped out the comments to save space ... but this service manages the user's locale; it's a key part of Tapestry 5's localization support. The implementation we'll see shortly works using HTTP Cookies, but that isn't important to the code that uses PersistentLocale.

public class PersistentLocaleImpl implements PersistentLocale
{
    private static final String LOCALE_COOKIE_NAME = "org.apache.tapestry5.locale";

    private final Cookies cookieSource;

    public PersistentLocaleImpl(Cookies cookieSource)
    {
        this.cookieSource = cookieSource;
    }

    public void set(Locale locale)
    {
        cookieSource.writeCookieValue(LOCALE_COOKIE_NAME, locale.toString());
    }

    public Locale get()
    {
        String localeCookieValue = getCookieValue();

        return localeCookieValue != null ? LocaleUtils.toLocale(localeCookieValue) : null;
    }

    private String getCookieValue()
    {
        return cookieSource.readCookieValue(LOCALE_COOKIE_NAME);
    }

    public boolean isSet()
    {
        return getCookieValue() != null;
    }
}

T5 IoC does all injection through the constructor. This is to encourage you to write your dependencies into final fields, which is thread safe. Typically, your services will be immutable objects: all fields final.

PersistentLocaleImpl has a dependency on another service, Cookies. And what is Cookies? It's another service interface. Notice that we don't have to do any extra configuration here ... since there's one, and only one, service that implements the Cookies interface, that's all the information Tapestry needs to wire things together.

Other service implementations inside Tapestry have as few as zero dependencies, and as many as eight. There's no theoretical limit, it's just that having more than a few dependencies is a design smell ... that you can break things into smaller pieces.

One of the hallmarks of coding using an IoC container is this level of terseness, also knows as passing the buck. Given that PersistentLocaleImpl is concerned with HTTP cookies, you'd think that it would, somehow, get ahold of the HttpServletRequest object and start invoking getCookies() and addCookie() on it ... but instead, all the details of interfacing with the Servlet API and the rather awkward API for HTTP cookies is swept into a corner, inside the Cookies service implementation.

That's great ... it makes the implementation of PersistentLocaleImpl (as well as any other code that happens to care about HTTP cookies) that much simpler and easier to test.

Service Lifecycle

Tapestry services have a specific lifecycle:

defined
Identified via the ServiceBinder, but not yet referenced
virtual
A proxy exists that has been injected as a dependency of some other service, but no methods of the proxy have been invoked
realized
The service has been instantiated with dependencies

The beauty of this is that your code is completely unaware of this; all the work inside Tapestry ... creating proxies, realizing service implementations, occurs in a lazy but thread-safe manner. It's as if all the services are instantiated at startup without taking the time to actually do that work.

Again, the appeal of an IoC container is that you get to break your application into tiny, easily tested bits, and the IoC container is responsible for connecting everything back together at runtime. It really leads to a new way of coding, and thinking about coding.

Service Builder Methods

Sometimes just instantiating a class is not enough; there may be additional configuration needed as part of instantiating the class. Tapestry 5 IoC's predecessor, HiveMind, accomplished such goals with complex service-building services. It ended up being a lot of XML.

T5 IoC accomplishes the same, and more, using service builder methods; module methods that construct a service. A typical case is when a service implementation needs to listen to events from some other service:

public static TranslatorSource buildTranslatorSource(ComponentInstantiatorSource componentInstantiatorSource, 
  ServiceResources resources)
{
    TranslatorSourceImpl service = resources.autobuild(TranslatorSourceImpl.class);

    componentInstantiatorSource.addInvalidationListener(service);

    return service;
}

Module methods prefixed with "build" are service builder methods. The service interface is defined from the return value (TranslatorSource). The service id is explicitly "TranslatorSource" (that is, everything after "build" in the method name).

Here, Tapestry has injected into the service builder method. ComponentInstantiatorSource is a service that fires events. ServiceResources is something else: it is a bundle of resources related to the service being constructed ... including the ability to instantiate an object including dependencies. What's great here is that buildTranslatorSource() doesn't need to know what the dependencies of TranslatorSourceImpl are, it can instantiate the class with dependencies using the autobuild() method. The service builder then adds the new service as a listener of the ComponentInstantiatorSource, before returning it.

This is a great separation of concerns: we have a construction concern (being an event listener) that's distinct from the operational concerns of TranslatorSource. And they are kept separate.

Conclusion

Tapestry IoC has simple and concise API for defining services and, in most cases, handles dependencies automatically. The end result is that it becomes child's play to divide-and-conquer: convert old, monolithic, hard to maintain code into small, easily tested, easily understood services.

In future postings, I'll go into more detail about the more advanced features of Tapestry: service scopes, service configurations and service decorations.

Ajax and Selenium: waitForCondition()

Selenium is a very useful tool but it can be very, very obtuse.

One challenge is dealing with Ajax; you might click on a button, but without a full page refresh, it's hard to know when to look for expected changes via Ajax and DHTML.

In the past, my test suites had short sleeps, a few hundred milliseconds. This makes them fail sporadically ... every once and a while on my MacBook Pro I'm doing so much other stuff while the tests run that the timing goes screwy.

You're then left with a difficult choice: sleep too short and the tests may fail. Sleep too long and your tests will always be slow.

Fortunately, there's a third option: Selenium's waitForCondition call. Of course, their documentation is worthless.

What it is supposed to do is evaluate a JavaScript snippet repeatedly, until the snippet returns true. However, it's tricky to get right. Like much in JavaScript, it's about context.

In my case, I wanted to wait for a client-side popup <div> to appear:

        type("amount", "abc");
        type("quantity", "abc");

        click(SUBMIT);

        waitForCondition("document.getElementById('amount:errorpopup')", "5000");

        assertText("//div[@id='amount:errorpopup']/span", "You must provide a numeric value for Amount.");
        assertText("//div[@id='quantity:errorpopup']/span", "Provide quantity as a number.");

JavaScript treats null as false, and getElementById() returns null if an element with the id does not exist.

I'm making the assumption that once one of two <div> elements appears, they both will. I then use some XPath to get the text inside the <span> inside each <div>, to make sure the correct message was displayed to the user.

But this code doesn't work.

The problem is that document isn't what you'd expect; I'm guessing that it's some other frame inside the browser (Selenium's UI and code executes in one frame, which runs the actual application inside the second frame).

The solution took some research and the sacrifice of a few small furry animals to obtain:

        waitForCondition("selenium.browserbot.getCurrentWindow().document.getElementById('amount:errorpopup')", "5000");

That works, and it works much faster than adding a Thread.sleep() in the middle of my code.

Tapestry @ JavaZone 2008

I'll be presenting on Tapestry 5 at JavaZone. I'll be in Lab 2, on Sept 18th, at 2:15. With less than an hour to talk about Tapestry 5 and compare it briefly to Wicket and Rails ... well, I'll be talking fast!

I also just noticed that there's a session on comparing IoC containers that includes Tapestry 5 IoC. That's Lab 6, on the 17th, at 5pm.

Friday, August 22, 2008

Stupid DateFormat

Working on some bugs related to the DateField component. Did you know that (for US English, anyway) DateFormat.getDateInstance(DateFormat.SHORT) provides back a DateFormat equivalent to "M/d/yy"?

That's a problem, because it has a tendency to format Dates to be two digit years. When it parses those same strings, it ends up considering the date to be in the first century AD.

Thus in this code:

  Date date1 = new Date(...);
  Date date2 = format.parse(format.format(date1));

date2 may or may not be the same as date1. Certainly any time information will be stripped out (this is expected), but often date2 will be in the wrong century.

I'm working right now to get the correct localized DateFormat, but ensure that the year portion is four digits, not two.

Thursday, August 21, 2008

Joshua Considers Tapestry 5

Josua Partogi has put together a nice quick intro to Tapestry 5. My only complaints are that the formatting makes the blog posting a bit hard to read, and that he included a lot of extra stuff in AppModule (put there by the Tapestry quickstart archetype) that's not required, such as the request timing filter. The archetype adds that as an example of what you can do. Finally, he uses the term "template" where all other documentation calls that type of component a "layout" (or, in Tapestry 4 terms, a "border").

Wednesday, August 13, 2008

My Ideas for Java Closures

According to Neal Gafter, the story for closures it still wide open.

As someone who writes a lot of code using closure-like mechanisms ... in the form of lots of inline inner classes ... I have a few idea of what I want in a solution. I think I'm writing some powerful and elegant code today, but that elegance in function is undermined by some severe awkwardness in its expression as Java code.

It really comes down to conciseness. I can accomplish pretty much everything I need using inner classes and holder objects, such as AtomicInteger and friends. But it ends up being more code than I'd like.

What I want (to borrow Stu's term) is to emphasize the essence of my logic, and strip away the ceremony: the naming of the interface (it should be known from context), the types of parameters (just the names, please), the list of thrown exceptions, etc.

First of all, let's constrain the problem. Closures would be defined in terms of an interface, an interface that contains a single method. Attempting to use the concise syntax with an interface that contains multiple methods would simply be a compiler error.

Second, the closure block should have free read/write access to parameters and local variables in the enclosing method. This can easily be accomplished with syntactic sugar: the variables can be converted into references to holder objects, such as AtomicInteger, that are stored on the heap. Today, shared fields must be final, to indicate that it is safe to share references to the object between the main method and any inner classes.

The hard part about sharing local variables in this way isn't implementing the syntactic sugar, it's about the updating of the information provided to the debugger so that the debugger can undo the syntactic sugar changes, and make variables in the enclosing method, or in the closure block, appear to be local.

Lastly, syntax. I think Groovy has the right syntax here. The important part is for the compiler to actually help out rather than for it to complain from the side-lines. Today's Java compiler has all the type information, but just uses that to build fancy error messages about what you should have typed. It should be using that type information to avoid the necessity of all the extra typing (that is, keyboard entry, not the need for types in the Ruby/Groovy sense of the word).

When a closure is passed to another method, the parameter type determines all the compiler should need to know. Likewise, when a closure is assigned to a variable, the variable defines the closure interface. Thus:

List<Widget> widgets = ... ;
Collections.sort(widgets,
  { w1, w2 -> return w1.getWidgetId().compareTo(w2.getWidgetId()); });

The generic type of the list, Widget, informs the generic type of the Comparator. Thus w1 and w2 are fully typed, as instances of Widget. The return type of the closure is pegged as int (also from the Comparator interface).

Side note: I'd also like to see a lot of other streamlining of Java, such as a Groovy-style implicit return.

In other words, the above could be expanded by the compiler to the following in terms of compilation:

List<Widget> widgets = ... ;
Collections.sort(widgets,
  new Comparator<Widget>()
  {
    public int compare(Widget w1, Widget w2)
    {
       return w1.getWidgetId().compareTo(w2.getWidgetId());
    }
  });

See, the essence is still there, the comparison of the widget Ids. But its now occluded by all that ceremony about interface names, method names, return values, generic types, and so forth.

A caveat: there are edge cases where we'll need to identify the closure interface type. This occurs when a method to be passed a closure is overridden. The compiler should be able to reduce the candidates based on parameter count, checked exceptions thrown inside the closure, and other factors ... but it may be necessary to implement an alternative syntax. For example:

ExecutorService service = ...;
Future<?> = service.submit(Runnable { performExpensiveOperation(); });

submit() is overridden to accept a Callable as well as a Runnable. Callable can return a value. Again, minimal syntax here: the interface name followed by the implementation of the closure method. This compares to the Groovy as keyword.

Now, it's easy to get carried away and put in stuff like Python style co-routines (the yield keyword), or want a syntax to allow the closure to force a return value from the enclosing block or method. <sarcasm> Yep, let's add a few more alien concepts to the language, people love that. </sarcasm>.

These are also not function objects, so you can't easily do magic things such as currying (currying is a way of pre-supplying some of the parameters to a function, such that a new function is created that takes fewer parameters). An "interface" that's curried is a whole new interface and that's OK by me.

I'm more more modest. I don't particularly want to add new features to the Java language, just new syntax for the compiler, to let it do the ugly plumbing. That's kind of my theory for Tapestry's relationship to Java and the Servlet API as well, and it works.

A few side notes:

Annotations could be used to help the compiler out. For example, if a common interface should be a closure, but has multiple methods, an annotation could be used to tell the compiler which method of the interface is applicable to use as a closure; any other methods (in the inner class) would be no-ops or (perhaps guided by additional annotations) failures.

Annotations on fields and parameters (or perhaps on the method) could help the compiler decide how to share visible variables: do we need to use a thread-safe approach (such as something based on AtomicReference) or simple, non-synchronized holder objects? The compiler could do some escape analysis as well to chose the best solution, but in many cases, it's on the coder's shoulders to make the right decision.

From what I can tell, my ideas are closest to the Concise Instance Creation Expressions proposal by Bob Lee, Doug Lea, and Josh Bloch. However, in my opinion, the compiler can do much more in terms of providing type information. I think CICE stumbles in that it allows for creation of classes, not just interfaces, and gets bogged down in defining closure types and parameter types ... again, things that (with the mandate of single-method interfaces), the compiler can do autonomously.

Likewise, CICE requires that variables visible to the inner block be marked "public". This to me is something that the compiler can analyze; it can identify any assignments to variables and promote such variables to stored-on-the-heap status. I don't see the need for final; the compiler has plenty of ability to determine if a parameter or local variable is ever updated within the body of a method (and the body of any inner classes or closures of that method).

My basic concept is: Less is More. Support fewer cases but do so more cleanly, more concisely, and more understandably. Simplify. Let the compiler do more work. Reduce the density and complexity of the Java code. Expose the essence.

Thursday, August 07, 2008

In Portland, even the cafes are Scalable

Portland is a town where, while walking to the gym, you can come across someone sitting at a sidewalk table of a local cafe, leafing through a hard-copy of Programming in Scala. We chatted for a moment (even though I was not quite awake yet). One more thing for me to do ... check out Lift.

And, yes, he actually had a print shop print and bind the PDF (as the book is only available electronically right now).

Wednesday, August 06, 2008

Coming to London, UK

It's looking very likely I'll be in London, UK next month for a bit of on-site training. I'm also speaking at JavaZone 2008. I'd love to optimize the number of flights I make to Europe, so if anyone is on the Continent is hankering for a little Tapestry training, now's a good time to get in touch!

After London, Suzy and I are then going to do a little trip around Europe, taking a couple of days in Paris and Amsterdam.

Latest FireBug understands redirects

Huzzah! One of the problems I've had using FireBug is that it didn't record a component event request long enough for me to see it; all I'd see was the follow-up page render request. But the latest FireBug is showing me the component event and the 302 response, and then the page render request, which gives a much more accurate idea of what is going on and how long it takes.