Thursday, April 24, 2008

This Week in Wonder

It's been a pretty busy week (and this is a lame effort to summarize 163 commit messages):

Ray Kiddy updated the movie example to 2008. New features include auto-populating DB and Apache Derby support.

Derby plugin
Used by BugTracker and ERMovies and now supported by ERPrototypes, it provides preliminary EOF support for Apache Derby. Most things seem to work, there are some issues with BLOBs, though.

If you ever have pages which *might* take a bit too long, but don't warrant a long response page, then this is for you. When you install this response handler (and use ERXApp) then a request that is taking too long is detached and the user is presented a "Uh, this might take a while, get some coffee" page - without you needing to do anything at all. And it has a "Stop now" button in case you don't actually want to finish the action.

This is also very useful when you are running in development and are dropped into a breakpoint. Normally, you'd get the adaptor error page but now it loops merrily until you continue.

loc:foo and negate:foo prefixes

These are the first implementations for the new prefix registration in the WOOgnl parser. They now also support carret bindings like ^title.

loc:value = bar

first asks the current localizer to handle the value of bar. This is way more powerful and readable than before, where you would either need to use

value =

or write an accessor method.

Ever had an accessor that was just the opposite of what you needed?

not:disabled = bar

helps here.

There is no easy way in Java to stop one thread from another. Actually, it's not possible at all unless the thread is waiting in the exact moment you try to stop it. We added a few crucial points where the current thread checks it it should quit: whe fetching a row from the DB and when the context sets a current component.

You just call ERXRuntimeUtilities.checkThreadInterrupt() at regular intervals and the thread that wants to stop calls ERXRuntimeUtilities.addThreadInterrupt(Thread thread, String message).

The REST framework is getting quite a bit of work done on it (with more coming soon).

The entity delegates resolver will now guess names that aren't registered (for instance, if you request /Manufacturer, it will look for a ManufacturerRestEntityDelegate), and you can now specify delegate names in Properties (ERXRest.Manufacturer.delegate=ERXUnsafeReadOnlyRestEntityDelegate).

The beginnings of the JSON input/output for ERXRest was committed, though not on by default (still experimental).

There are several new convenience methods for registering ERXRest. The simplest is to add:

ERXRestRequestHandler.register(new YourRestAuthenticationDelegate(), true, true);

to your Application constructor and add Properties entries for registering delegates.

ERXRest now supports non-integer keys. If a key in the URL isn't the property of an entity, it is treated as a key. You can now also specify a custom attribute on your EO's to act as the "id" value by setting:

, which allows your EO's to expose non-PK attributes as the lookup value. For instance, you could have a UUID "external ID" that can be used for syncing EO's across multiple applications.

Ajax Load-on-Demand
[MS: This is a repost from of the announcement the wonder-disc list]
This is the largest change to Ajax framework in a while, and because it introduces some breaking API changes, I wanted to explain what it's all about.

Previously, if you had a page that revealed a new Ajax component (new = first use on the page) only in an Ajax refresh, you are probably familiar with the problem that the necessary Javascript dependencies were not loaded correctly. The cause of this is that the component was hidden and did not have a chance to inject its dependencies into the head tag. With this most recent commit, Ajax framework (transparently) supports load-on-demand of Javascript dependencies. It keeps track of which scripts (and CSS) have been loaded on your page (both on the original render as well as subsequent Ajax requests) and if a new component introduced in an Ajax update requires a script that has not been loaded, it will switch to render the dependency with the new load-on-demand method.

The Javascript side of load-on-demand is actually a feature that appears that it will be in Prototype 2.0 which we have brought forward into wonder.js, and the Java side is just the usual Project Wonder black magic :)

So about breaking API changes and behavior changes:

Most of the ERXWOContext response rewriting methods have been moved to ERXResponseRewriter. They never really made a lot of sense on ERXWOContext, but especially now that these methods actually potentially consider information that crosses contexts, it made sense to reorganize them. Additionally, several of the API's have been changed -- most just to take a WOContext where they didn't before. The most notable API change is that previously the insertion behavior was controlled with two booleans which have now been replaced by an enumerated type that more clearly defines what the behavior of the insertion methods will be when the head tag is not present (either because it's just missing or because you're in an Ajax update). For most people, the only change you may need to make is to add the missing WOContext parameter if it's needed (the other variant of the method probably was not used very much).

As for behavioral changes, there is really one PRIMARY one (well aside from the whole load-on-demand thing). The big behavioral change is that previously you could actually "insert" script and css into the head tag BEFORE it actually existed. Generally this is only even an issue when you try to add script/css in your Page Wrapper by overriding appendToResponse and calling those method BEFORE super.appendToResponse (meaning your page wrapper has not yet rendered the head tag, but you're asking to insert into it). Because of some of the API changes, it was necessary to REMOVE this ability (long story, but the API's require a WOContext and the method that previously provided this ability did not have access to the WOContext to fulfill the API). The fix for this is relatively simple -- Just move any calls to those functions in your page wrapper AFTER the super.appendToResponse. This probably won't impact many people, but if it DOES impact you, it will manifest as your CSS and Javascript not injecting into the head tag and a warning will be generated on the console explaining what happened.

ERXStyleSheet and ERXJavaScript have been modified to register their loaded resources with the same system, so if you use an ERXStyleSheet or ERXJavaScript, it will not double-load if you later load scripts/css with ERXResponseRewriter. ERXStyleSheet will now SKIP rendering its stylesheet if it has already been loaded (so you can put ERXStyleSheet in Ajax rendered components in addition to using ERXResponseRewriter and it will behave the same). ERXJavaScript right now does not skip rendering, but it DOES register that it has loaded, so it will satisfy dependencies if you later use ERXResponseRewriter to load scripts on-demand.

If for some reason you want to turn off load-on-demand, you can 1) just keep doing things the way you were -- declare your scripts at the top level so they have all been loaded by the time the Ajax components render, or 2) set er.extensions.loadOnDemand=false.

While the actually lines of code of these changes is relatively small, it's conceptually sort of significant, so please try out your Ajax apps and let me know if you see any oddities. Hopefully this will make the components much more encapsulated and far easier to use for everyone ... Apologies for any backwards compatibility issues this introduces in the short term.

Misc Ajax
AjaxDroppable has an onBeforeDrop binding that lets you connect a javascript function before the drop happens. AjaxDroppable can also now act like a submit button instead of a link by setting submit = true. Both AjaxDraggable and AjaxDroppable got a shiny new paint job, too -- all the javascript that used to generate in the component output is now moved to wonder.js and the generated output is substantially smaller.

AjaxObserveField has a new onBeforeSubmit binding that allows you to return false to deny the submit.

ERD2WDirectAction now supports ErrorFoo?__message=bar calls which is an easy way to put up a error page.

We moved the work-in-progress stuff from ERXFetchSpecification to ERXGroupingFetchSpecification.

ERXObjectStoreCoordinatorSynchronizer: The synchronizer now exposes the ability for fine-grained sync controls between stacks. For instance, if you application is a write-mostly app, it may be undesirable to have inserts synced between EOF stacks. You can now setDefaultSettings on the synchronizer (or set the settings per-object store) to control exactly which types of operations will be synced across stacks, including turning syncing off entirely for particular stacks.

No comments:

Post a Comment