Thursday, November 5, 2009

What's Old in Wonder

It's been a long time since the last What's New in Wonder -- almost 8 months. We've been busy, quietly making your life cooler :) There's actually been quite a bit of activity in Wonder, including contributions from lots of people outside the regulars. We've had a lot of Jiras filed (many with patches! thank you).

Thanks to everyone who contributed bugs, patches, tests, and features over the 8 months -- Anjo, Chuck, Quinton, Timo, Lachlan, Henrique, Ravi, Denis, Ray, Ramsey, Kieran, Travis(es), Michael, and anyone else I might be forgetting.

The synopsis below doesn't do justice to any of the items listed -- I encourage you to read the docs on each of them for more information, but it should at least give you a starting point for finding more information. As always, my own stuff is disproportionately weighted in the synopses :)

New Components


  • ERXSwitchComponent - patched in, hides the component name
  • ERXResponseComponent - lets you wrap a WOActionResults in a WOComponent implementation
  • ERXBooleanSelector - Yes/No/Blank picker
  • ERXClippy - wrapper around the Clippy flash clipboard access layer
  • ERXPodcastRssPage

Ajax

  • Bunch of enhancements to AjaxModalDialog
  • iBox updated to 2.2
  • AjaxModalContainer tweaked to support dynamic resizing
  • Updated to Prototype 1.6.1 and Scriptaculous 1.8.3
  • New experimental support for returning components from Ajax action methods (when used with replaceID binding)
  • New experimental push/keep-alive support

D2W

  • New D2W page/component metrics
  • Cleanup on the 47 different boolean picker components
  • ERDEditableList brought over from Diva

EOF

  • bunch of new tools for tracking down editing context lock problems
  • support for tracking locks on ERXDatabaseContext
  • bunch of tweaks and fixes and new bugs but then more new fixes for autolocking (in particular, support for sharing an autolocked ec across threads)
  • support for bind variables with FrontBase
  • migration fixes for SQLServer and Derby
  • automatic batch faulting - basically Wonder watching your back about prefetching, preventing scenarios where you would have gotten a million individual fetches before
  • ERXPrefixQualifierTraversal - walks a qualifier and prepends a keypath to every key of the qualifier

ERRest

  • supports non-EO's using EOClassDescriptions (via a new BeanInfoClassDescription)
  • supports non-model relationships on EO's (via a new class description factory that can handle EOEntityCD's and BeanInfoCD's for the same class)
  • format delegates for remapping commons keys (like id and type)
  • ERXKeyFilter now has a security delegate for implementation fancier rules
  • ERXRestFetchSpecification - makes it really easy to fetch based on query params with security filters
  • ERXFilteredQualifierTraversal - provides support for filtering a qualifier with an ERXKeyFilter (so people can't fetch on salary > x if they're not allowed to see salary)
  • support for deferring the generation of rest responses, so you can pass requests between controllers (this provides support for having compound controllers, like what would be needed for a Gianduia fetching controller)
  • easier support for generating html responses with rest controllers
  • ERXRouteLink - generate links to route controllers

SnapshotExplorer

  • new framework for exploring the snapshots that are currently loaded into memory in your application

Diva Look Framework

  • ERDivaLook/ERPrototaculous/ERDivaLookExample frameworks are a new D2W look focused on XHTML div content styled with css rather than the older table-based looks. Additionally it has its own Ajax framework (not to be confused with Wonder's existing Ajax.framework) based on WO 5.4's ajax request handler.

ERMovies/ERMoviesLogic

  • Movies example moved into Wonder

ERChronic

  • Patched to match trunk of chronic

ERAttachment

  • Support for resizing attachments on upload
  • SipsImageProcessor - uses sips commandline tool to thumbnail (not as fast as ImageIO JNI imp, but less to build)

WOJavaRebel

  • huge performance improvements
  • support for model reloading
  • updated to new JavaRebel version

ERPDFGeneration

  • ERPDFGeneration provides both a utility class and a wrapper component for generating
    PDF documents from XHTML markup. Two PDF generation engines are currently supported,
    FlyingSaucer (xhtmlrenderer) [1] and Useful Java Application Components (UJAC) [2],
    however additional parser based engines like FOP could be added fairly easily.

Validity

  • i guess it runs now? it got a bunch of build-related fixes at least

ERMemoryAdaptor

  • all cleaned up and shiny
  • split into memory store and entity store, which can be a basis for other custom adaptors
  • support for flattened attributes

WOPayPal

  • Sandbox support

Testing

  • build scripts now support running test cases
  • bunch of test cases added

Misc

  • ERXSignalHandler - "multicast" signal handler
  • ERXProperties/Configuration cleaned up dramatically
  • ERXComponentUtilities.inheritTemplateFrom - make one component inherit the template of another component
  • ERIUIExample made fancier

Build Server

  • Moved entire to Hudson - http://webobjects.mdimension.com/hudson
  • Rebuilds immediately on commit
  • All applications and examples are built fully embedded (= easy to download and run now)

Sunday, April 19, 2009

Need More Rest

Note: This is all brand new and to be considered experimental right now, but I thought I'd give you guys a heads-up:

ERXRest can do a lot of various things, but I was never happy with the API and the complexity of the interfaces you have to implement to use it. Anjo did some work with ERD2REST, which is cool, but I still have a bunch of cases where I just want something like what Rails offers -- a very easy way to map annotated URLs onto (direct) action methods. When you just want to quickly make a json interface to your app (especially CRUD interfaces), but with support for additional custom actions (which ERXRest doesn't address), the rails approach makes a lot of sense ... So here are some new API's to try to make that easier:

in your Application constructor:


ERXRouteRequestHandler routeRequestHandler = new ERXRouteRequestHandler();
routeRequestHandler.addDefaultRoutes(Reminder.ENTITY_NAME);
routeRequestHandler.addDefaultRoutes(Person.ENTITY_NAME);
ERXRouteRequestHandler.register(routeRequestHandler);

(you can also add custom routes -- i.e. "/people/{person:Person}/company/{company:Company}/{something:String}" -- but the one above defines all the default routes that rails supports ... check out the javadoc for ERXRestRequestHandler for more info).

then you can make a controller class:

public class PeopleController extends ERXRouteController {
public PeopleController(WORequest request) {
super(request);
}

public Person person() {
Person person = (Person) objects().objectForKey("person");
return person;
}

public ERXKeyFilter personFilter() {
ERXKeyFilter filter = ERXKeyFilter.filterWithAttributes();
filter.include(Person.PREFERENCE_GROUPS).includeAttributes();
return filter;
}

public WOActionResults createAction() throws Exception {
ERXKeyFilter personFilter = personFilter();
personFilter.include(Person.COMPANY);
Person person = (Person) create(Person.ENTITY_NAME, personFilter);
editingContext().saveChanges();
return response(personFilter(), person);
}

public WOActionResults updateAction() throws Exception {
Person person = person();
update(person, personFilter());
editingContext().saveChanges();
return response(personFilter(), person);
}

public WOActionResults showAction() {
Person person = person();
return response(personFilter(), person);
}

public WOActionResults indexAction() throws Exception {
NSArray people = Person.fetchPersons(editingContext(), null, Person.LAST_NAME.asc().then(Person.FIRST_NAME.asc()));
return response(personFilter(), editingContext(), Person.ENTITY_NAME, people);
}
}

This is basically a DirectAction class, but it has a bunch of tools to make it easy to do the rest creates, updates, and lookups ... there is no security by default (just like rails), so you have to enforce security however makes sense, but it handles xml, json, and plist requests and for the cases where you're just doing relatively straightforward things, this is way easier than the other ERXRest stuff, though you trade off some optimized fetching and automatic security filtering that ERXRest does in exchange for the simplicity.

The determination of what to include/exclude both in rendering and in parsing is done with ERXKeyFilters, which allow hierarchical definitions of include/exclude filters for keypaths (so you say things like: start with an "include all attributes" base, but exclude "password", then include the "tasks" relationship, but don't show any attributes for that (so you just get task ids)). The code for that would be:


ERXKeyFilter filter = ERXKeyFilter.filterWithAttributes();
filter.exclude(Person.PASSWORD);
filter.include(Person.TASKS);


As an example of actually hitting the API, btw:

curl -X PUT -d '{ lastName="SchragTestAlso"; preferenceGroups=( {id=1000012; name="SomeName2"; } ); }' http://vdoop.local:51915/cgi-bin/WebObjects/MDTask.woa/ra/person/1000008.plist

this updates the person with id 1000008 with plist format, sets the last name to "SchragTestAlso", and replaces their preference groups with a single existing preference group id 1000012 and also updates the name of that group to be "SomeName2".

curl -X PUT -d '{ lastName:"SchragTestAlso"; preferenceGroups:[ {id:1000012; name:"SomeName2"; } ]; }' http://vdoop.local:51915/cgi-bin/WebObjects/MDTask.woa/ra/person/1000008.json

is the same thing in JSON, and

curl -X PUT -d '<Person><lastName>SchragTestAlso</lastName><preferenceGroups><PreferenceGroup id="1000012"><name>SomeName2</name></PreferenceGroup></preferenceGroups></Person>' http://vdoop.local:51915/cgi-bin/WebObjects/MDTask.woa/ra/person/1000008.xml

is the same thing in XML ... notice that just by changing the extension it automagically does request and response filtering for you with the right parser/writer.

Saturday, March 21, 2009

The "I Have A Day Job" Edition

ERRest
support for plist and json responses

support for simple qualifiers and sort orderings in query params

lots of API's for programmatically generating responses

ERDirectToRest
initial pass at a D2W version of the ERRest framework

ERPlot
Updated to latest JFreeChart

EOF
ERXExistsQualifier - creates a query clause based on the SQL exists keyword and a subquery

Support for custom prototype overrides in ERXModelGroup.

ERXEnterpriseObjectCache substantially overhauled to .. well .. not break.

Examples
TickTockMan - example app that performs various time-related tasks. Hopefully, this can become a resource for people trying to understand the use of time, time intervals, time zones and associated objects in WebObjects applications.

Über - Wonder testing app designed for automated testing against new versions of WebObjects.

Ajax
Ajax scripts are compressed during the build process.

AjaxUtils.updateDomElement - appends JavaScript code to the given AjaxResponse that updates the content of the DOM Element with the given ID to the specified value. Useful if you want to update multiple small regions on a page with a single request, e.g. when an AjaxObserveField triggers an action.

AjaxModalDialog - LOTS of enhancements. Check the javadoc for better converage.

ERAttachment
ERImageProcessors - Support for image processing with several variants (Java2D, ImageMagick, and JNI-based CoreImage/ImageIO). This will ultimately be used to support automatic thumbnailing.

Maven
BUILD.txt updated with latest maven build instructions

Misc
Utilities/WOInstall - source of WOInstaller.jar

ERXValueUtilities and related ERXProperties methods were rewritten to be much more consistent and more forward compatible with future version of WO + actually has test cases

WOJavaRebel
Updated for JavaRebel 2.0

ERChronic
Updated to match (roughly) Ruby Chronic's 0.3.0 version

JavaMonitor
refactored the confirm pages to use just one page

added 'stop all' for selected instances

added 'delete all' for selected instances

more directactions controls

/admin/ action added (will allow for rest-like urls) returning JSON compatible output on info

added bounce action

Components
ERXLanguageMenu - generic picker for selecting your current language

... and a gazillion bug fixes