<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DEUDRno9eip7ImA9WhRUFko.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848</id><updated>2012-01-27T09:57:57.462-05:00</updated><category term="tagging" /><title>Project Wonder</title><subtitle type="html">Fiendishly clever!</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://projectwonder.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Anjo Krank</name><uri>http://www.blogger.com/profile/12153571432284820771</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/projectwonder" /><feedburner:info uri="projectwonder" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CkAGRXgycCp7ImA9WxBWGEw.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-8306199430912090667</id><published>2010-02-10T09:02:00.000-05:00</published><updated>2010-02-10T09:05:24.698-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-10T09:05:24.698-05:00</app:edited><title>This Three Months in Wonder</title><content type="html">&lt;span style="font-weight:bold;"&gt;EOF&lt;/span&gt;&lt;br /&gt;An H2PlugIn has been added to Wonder to support the H2 Database Engine (&lt;a href="http://www.h2database.com "&gt;http://www.h2database.com&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Components&lt;/span&gt;&lt;br /&gt;The ERReCaptcha component was added to ERCaptcha.framework -- this adds support for &lt;a href="http://recaptcha.net"&gt;http://recaptcha.net&lt;/a&gt; in a way that is API-compatible with ERXSimpleSpamCheck.&lt;br /&gt;&lt;br /&gt;ERAkismet has been added to ERCatpcha.framework. ERAkismet adds support for the Akismet spam identification service that is API-compatible with ERXSimpleSpamCheck.&lt;br /&gt;&lt;br /&gt;ERPOFCChart has been added to the ERPlot framework. This component adds a simple wrapper around the OpenFlashCharts2 flash charting tool.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERRest&lt;/span&gt;&lt;br /&gt;ERRest now supports JSR-311-style annotations if you prefer that approach:&lt;br /&gt;&lt;br /&gt;Application.java:&lt;br /&gt; routeController.addRoutes(Person.ENTITY_NAME, PersonController.class);&lt;br /&gt;   &lt;br /&gt;PersonController.java:&lt;br /&gt; @GET @Path("/person/{person:Person}")&lt;br /&gt; public WOActionResults view(@PathParm("person") Person person) {&lt;br /&gt; ...&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Migrations&lt;/span&gt;&lt;br /&gt;Basic migrations will run against MemoryAdaptor now (or .. appear to), which helps when running test cases.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Examples&lt;/span&gt;&lt;br /&gt;BugTracker app can now run with MemoryAdaptor, which requires zero setup. This should make it much easier to fire up the example app to see what Wonder can do. To run with memory adaptor, you can launch from eclipse with the VM Arguments "-Xmx512M -Duser.name=Memory".&lt;br /&gt;&lt;br /&gt;The new ERComponentTour example app shows some components with some example uses.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Tools&lt;/span&gt;&lt;br /&gt;RuleModeler now supports adding documentation to rules.&lt;br /&gt;&lt;br /&gt;ERD2WGraphVizPage in ERD2W can spit out a graphviz file that represents your EOModel.&lt;br /&gt;&lt;br /&gt;JavaRebel is now JRebel, so WOJavaRebel is now WOJRebel (and updated to the latest-and-greatest). Q's done a bunch of work on this and now supports EOModel reloading. He says JRebel is much faster in the new versions, too. I hate myself for not using this. In fact, I'm going to hook this up right after I finish writing all this up.&lt;br /&gt;&lt;br /&gt;ERProfiling is a cool new framework for profiling your WO apps in a way that actually understands WO. For more information, &lt;a href="http://webobjects.mdimension.com/hudson/job/Wonder53/javadoc/er/profiling/package-summary.html"&gt;read more here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Adaptors&lt;/span&gt;&lt;br /&gt;Anjo started work on an Apache Mina-based WOAdaptor (&lt;a href="http://mina.apache.org/"&gt;http://mina.apache.org/&lt;/a&gt;). I believe this is still experimental.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;D2W&lt;/span&gt;&lt;br /&gt;Ravi pushed up a new look into Wonder -- "ERDivaliteLook" as well as the ERDivaliteExample example app to show it off.&lt;br /&gt;&lt;br /&gt;"It's intended as a transitionary point to migrate WO/D2W apps to Diva look.&lt;br /&gt;As such it's:&lt;br /&gt;&lt;br /&gt;1. HTML4 table-less markup.&lt;br /&gt;2. CSS and Selenium tests are interchangeable with a full Diva look app.&lt;br /&gt;3. No Ajax.&lt;br /&gt;4. WO 5.3+  compatible."&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Documentation&lt;/span&gt;&lt;br /&gt;Ray has been doing all kinds of great work making the documentation for Wonder more accessible and useful. This has included adding a new doclet for showing components along with their component bindings (see &lt;a href="http://webobjects.mdimension.com/hudson/job/Wonder53/1051/javadoc/components.html"&gt;here&lt;/a&gt;) as well as a doclet for showing the available d2wkeys for D2W components (&lt;a href="http://webobjects.mdimension.com/hudson/job/Wonder53/1051/javadoc/d2wlist.html"&gt;here&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Testing&lt;/span&gt;&lt;br /&gt;Ray has also done a lot of work on the test cases and getting them to run properly from ant. You can also run all the test cases from within Eclipse in the JUnit runner.&lt;br /&gt;&lt;br /&gt;ERMovies now has Selenium test scripts.&lt;br /&gt;&lt;br /&gt;ERSelenium now has support for taking screenshots in the standalone runner.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Removals&lt;/span&gt;&lt;br /&gt;The SproutCore framework and example app have been removed. It was an interesting experiment, but ultimately would have been too labor-intensive to keep it maintained alongside the official SproutCore framework.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-8306199430912090667?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/nfGAG_ChPKQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/8306199430912090667/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2010/02/this-three-months-in-wonder.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/8306199430912090667?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/8306199430912090667?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/nfGAG_ChPKQ/this-three-months-in-wonder.html" title="This Three Months in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2010/02/this-three-months-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YAQ3k7fCp7ImA9WxNUFU8.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-53918881685888135</id><published>2009-11-05T22:34:00.000-05:00</published><updated>2009-11-06T10:25:42.704-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-06T10:25:42.704-05:00</app:edited><title>What's Old in Wonder</title><content type="html">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).&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;New Components&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;ERXSwitchComponent - patched in, hides the component name&lt;br /&gt;&lt;li&gt;ERXResponseComponent - lets you wrap a WOActionResults in a WOComponent implementation&lt;br /&gt;&lt;li&gt;ERXBooleanSelector - Yes/No/Blank picker&lt;br /&gt;&lt;li&gt;ERXClippy - wrapper around the Clippy flash clipboard access layer&lt;br /&gt;&lt;li&gt;ERXPodcastRssPage&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Bunch of enhancements to AjaxModalDialog&lt;br /&gt;&lt;li&gt;iBox updated to 2.2&lt;br /&gt;&lt;li&gt;AjaxModalContainer tweaked to support dynamic resizing&lt;br /&gt;&lt;li&gt;Updated to Prototype 1.6.1 and Scriptaculous 1.8.3&lt;br /&gt;&lt;li&gt;New experimental support for returning components from Ajax action methods (when used with replaceID binding)&lt;br /&gt;&lt;li&gt;New experimental push/keep-alive support&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;D2W&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;New D2W page/component metrics&lt;br /&gt;&lt;li&gt;Cleanup on the 47 different boolean picker components&lt;br /&gt;&lt;li&gt;ERDEditableList brought over from Diva&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;EOF&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;bunch of new tools for tracking down editing context lock problems&lt;br /&gt;&lt;li&gt;support for tracking locks on ERXDatabaseContext&lt;br /&gt;&lt;li&gt;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)&lt;br /&gt;&lt;li&gt;support for bind variables with FrontBase&lt;br /&gt;&lt;li&gt;migration fixes for SQLServer and Derby&lt;br /&gt;&lt;li&gt;automatic batch faulting - basically Wonder watching your back about prefetching, preventing scenarios where you would have gotten a million individual fetches before&lt;br /&gt;&lt;li&gt;ERXPrefixQualifierTraversal - walks a qualifier and prepends a keypath to every key of the qualifier&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERRest&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;supports non-EO's using EOClassDescriptions (via a new BeanInfoClassDescription)&lt;br /&gt;&lt;li&gt;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)&lt;br /&gt;&lt;li&gt;format delegates for remapping commons keys (like id and type)&lt;br /&gt;&lt;li&gt;ERXKeyFilter now has a security delegate for implementation fancier rules&lt;br /&gt;&lt;li&gt;ERXRestFetchSpecification - makes it really easy to fetch based on query params with security filters&lt;br /&gt;&lt;li&gt;ERXFilteredQualifierTraversal - provides support for filtering a qualifier with an ERXKeyFilter (so people can't fetch on salary &gt; x if they're not allowed to see salary)&lt;br /&gt;&lt;li&gt;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)&lt;br /&gt;&lt;li&gt;easier support for generating html responses with rest controllers&lt;br /&gt;&lt;li&gt;ERXRouteLink - generate links to route controllers&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;SnapshotExplorer&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;new framework for exploring the snapshots that are currently loaded into memory in your application&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Diva Look Framework&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;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.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERMovies/ERMoviesLogic&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Movies example moved into Wonder&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERChronic&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Patched to match trunk of chronic&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERAttachment&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Support for resizing attachments on upload&lt;br /&gt;&lt;li&gt;SipsImageProcessor - uses sips commandline tool to thumbnail (not as fast as ImageIO JNI imp, but less to build)&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WOJavaRebel&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;huge performance improvements&lt;br /&gt;&lt;li&gt;support for model reloading&lt;br /&gt;&lt;li&gt;updated to new JavaRebel version&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERPDFGeneration&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;ERPDFGeneration provides both a utility class and a wrapper component for generating&lt;br /&gt;PDF documents from XHTML markup. Two PDF generation engines are currently supported,&lt;br /&gt;FlyingSaucer (xhtmlrenderer) [1] and Useful Java Application Components (UJAC) [2],&lt;br /&gt;however additional parser based engines like FOP could be added fairly easily.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Validity&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;i guess it runs now? it got a bunch of build-related fixes at least&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERMemoryAdaptor&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;all cleaned up and shiny&lt;br /&gt;&lt;li&gt;split into memory store and entity store, which can be a basis for other custom adaptors&lt;br /&gt;&lt;li&gt;support for flattened attributes&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WOPayPal&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Sandbox support&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Testing&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;build scripts now support running test cases&lt;br /&gt;&lt;li&gt;bunch of test cases added&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;ERXSignalHandler - "multicast" signal handler&lt;br /&gt;&lt;li&gt;ERXProperties/Configuration cleaned up dramatically&lt;br /&gt;&lt;li&gt;ERXComponentUtilities.inheritTemplateFrom - make one component inherit the template of another component&lt;br /&gt;&lt;li&gt;ERIUIExample made fancier&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Build Server&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Moved entire to Hudson - http://webobjects.mdimension.com/hudson&lt;br /&gt;&lt;li&gt;Rebuilds immediately on commit&lt;br /&gt;&lt;li&gt;All applications and examples are built fully embedded (= easy to download and run now)&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-53918881685888135?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/v-S4sJv9lKY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/53918881685888135/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2009/11/whats-old-in-wonder.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/53918881685888135?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/53918881685888135?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/v-S4sJv9lKY/whats-old-in-wonder.html" title="What's Old in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2009/11/whats-old-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QBQno9eip7ImA9WxJTEkk.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-5849034923305715624</id><published>2009-04-19T23:45:00.001-04:00</published><updated>2009-04-20T11:29:13.462-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-20T11:29:13.462-04:00</app:edited><title>Need More Rest</title><content type="html">Note: This is all brand new and to be considered experimental right now, but I thought I'd give you guys a heads-up:&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;in your Application constructor:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ERXRouteRequestHandler routeRequestHandler = new ERXRouteRequestHandler();&lt;br /&gt;routeRequestHandler.addDefaultRoutes(Reminder.ENTITY_NAME);&lt;br /&gt;routeRequestHandler.addDefaultRoutes(Person.ENTITY_NAME);&lt;br /&gt;ERXRouteRequestHandler.register(routeRequestHandler);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;(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).&lt;br /&gt;&lt;br /&gt;then you can make a controller class:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class PeopleController extends ERXRouteController {&lt;br /&gt;  public PeopleController(WORequest request) {&lt;br /&gt;    super(request);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Person person() {&lt;br /&gt;    Person person = (Person) objects().objectForKey("person");&lt;br /&gt;    return person;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public ERXKeyFilter personFilter() {&lt;br /&gt;    ERXKeyFilter filter = ERXKeyFilter.filterWithAttributes();&lt;br /&gt;    filter.include(Person.PREFERENCE_GROUPS).includeAttributes();&lt;br /&gt;    return filter;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public WOActionResults createAction() throws Exception {&lt;br /&gt;    ERXKeyFilter personFilter = personFilter();&lt;br /&gt;    personFilter.include(Person.COMPANY);&lt;br /&gt;    Person person = (Person) create(Person.ENTITY_NAME, personFilter);&lt;br /&gt;    editingContext().saveChanges();&lt;br /&gt;    return response(personFilter(), person);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public WOActionResults updateAction() throws Exception {&lt;br /&gt;    Person person = person();&lt;br /&gt;    update(person, personFilter());&lt;br /&gt;    editingContext().saveChanges();&lt;br /&gt;    return response(personFilter(), person);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public WOActionResults showAction() {&lt;br /&gt;    Person person = person();&lt;br /&gt;    return response(personFilter(), person);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public WOActionResults indexAction() throws Exception {&lt;br /&gt;    NSArray&lt;Person&gt; people = Person.fetchPersons(editingContext(), null, Person.LAST_NAME.asc().then(Person.FIRST_NAME.asc()));&lt;br /&gt;    return response(personFilter(), editingContext(), Person.ENTITY_NAME, people);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ERXKeyFilter filter = ERXKeyFilter.filterWithAttributes();&lt;br /&gt;filter.exclude(Person.PASSWORD);&lt;br /&gt;filter.include(Person.TASKS);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As an example of actually hitting the API, btw:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;curl -X PUT -d '{ lastName="SchragTestAlso"; preferenceGroups=( {id=1000012; name="SomeName2"; } ); }' http://vdoop.local:51915/cgi-bin/WebObjects/MDTask.woa/ra/person/1000008.plist&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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".  &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;curl -X PUT -d '{ lastName:"SchragTestAlso"; preferenceGroups:[ {id:1000012; name:"SomeName2"; } ]; }' http://vdoop.local:51915/cgi-bin/WebObjects/MDTask.woa/ra/person/1000008.json&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;is the same thing in JSON, and&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;curl -X PUT -d '&amp;lt;Person&gt;&amp;lt;lastName&gt;SchragTestAlso&amp;lt;/lastName&gt;&amp;lt;preferenceGroups&gt;&amp;lt;PreferenceGroup id="1000012"&gt;&amp;lt;name&gt;SomeName2&amp;lt;/name&gt;&amp;lt;/PreferenceGroup&gt;&amp;lt;/preferenceGroups&gt;&amp;lt;/Person&gt;' http://vdoop.local:51915/cgi-bin/WebObjects/MDTask.woa/ra/person/1000008.xml&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-5849034923305715624?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/UOjsbwacrD4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/5849034923305715624/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2009/04/need-more-rest.html#comment-form" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/5849034923305715624?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/5849034923305715624?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/UOjsbwacrD4/need-more-rest.html" title="Need More Rest" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>8</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2009/04/need-more-rest.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYFSHo8fCp7ImA9WxVUFkk.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-1061259532817201540</id><published>2009-03-21T09:43:00.000-04:00</published><updated>2009-03-21T09:45:19.474-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-21T09:45:19.474-04:00</app:edited><title>The "I Have A Day Job" Edition</title><content type="html">&lt;span style="font-weight:bold;"&gt;ERRest&lt;/span&gt;&lt;br /&gt;support for plist and json responses&lt;br /&gt;&lt;br /&gt;support for simple qualifiers and sort orderings in query params&lt;br /&gt;&lt;br /&gt;lots of API's for programmatically generating responses&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERDirectToRest&lt;/span&gt;&lt;br /&gt;initial pass at a D2W version of the ERRest framework&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERPlot&lt;/span&gt;&lt;br /&gt;Updated to latest JFreeChart&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;EOF&lt;/span&gt;&lt;br /&gt;ERXExistsQualifier - creates a query clause based on the SQL exists keyword and a subquery&lt;br /&gt;&lt;br /&gt;Support for custom prototype overrides in ERXModelGroup.&lt;br /&gt;&lt;br /&gt;ERXEnterpriseObjectCache substantially overhauled to .. well .. not break.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Examples&lt;/span&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Über - Wonder testing app designed for automated testing against new versions of WebObjects.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;Ajax scripts are compressed during the build process.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;AjaxModalDialog - LOTS of enhancements. Check the javadoc for better converage.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERAttachment&lt;/span&gt;&lt;br /&gt;ERImageProcessors - Support for image processing with several variants (Java2D, ImageMagick, and JNI-based CoreImage/ImageIO). This will ultimately be used to support automatic thumbnailing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt;&lt;br /&gt;BUILD.txt updated with latest maven build instructions&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc&lt;/span&gt;&lt;br /&gt;Utilities/WOInstall - source of WOInstaller.jar&lt;br /&gt;&lt;br /&gt;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&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WOJavaRebel&lt;/span&gt;&lt;br /&gt;Updated for JavaRebel 2.0&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERChronic&lt;/span&gt;&lt;br /&gt;Updated to match (roughly) Ruby Chronic's 0.3.0 version&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JavaMonitor&lt;/span&gt;&lt;br /&gt;refactored the confirm pages to use just one page&lt;br /&gt;&lt;br /&gt;added 'stop all' for selected instances&lt;br /&gt;&lt;br /&gt;added 'delete all' for selected instances&lt;br /&gt;&lt;br /&gt;more directactions controls&lt;br /&gt;&lt;br /&gt;/admin/ action added (will allow for rest-like urls) returning JSON compatible output on info&lt;br /&gt;&lt;br /&gt;added bounce action&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Components&lt;/span&gt;&lt;br /&gt;ERXLanguageMenu - generic picker for selecting your current language&lt;br /&gt;&lt;br /&gt;... and a gazillion bug fixes&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-1061259532817201540?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/y3aUovd6yzM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/1061259532817201540/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2009/03/i-have-day-job-edition.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/1061259532817201540?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/1061259532817201540?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/y3aUovd6yzM/i-have-day-job-edition.html" title="The &quot;I Have A Day Job&quot; Edition" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2009/03/i-have-day-job-edition.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4AQn4zeip7ImA9WxRaEko.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-503435827705554512</id><published>2008-12-14T10:51:00.000-05:00</published><updated>2008-12-14T11:09:03.082-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-14T11:09:03.082-05:00</app:edited><title>This Week in Wonder</title><content type="html">&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;AjaxModalDialogOpener lets you separate the opening of a modal dialog from the dialog itself.&lt;br /&gt;&lt;br /&gt;Updated to Scriptaculous 1.8.2&lt;br /&gt;&lt;br /&gt;AjaxSortOrder is an ajax version of ERXSortOrder.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Components&lt;/span&gt;&lt;br /&gt;Support for quicktime attachments in ERAttachment.&lt;br /&gt;&lt;br /&gt;ERXSimpleSpamCheck is an implementation of Hugi's simple spam blocker, which will cause forms to fail validation unless a particular block of javascript has been executed by the client.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;EOF&lt;/span&gt;&lt;br /&gt;Wonder Migrations can now be used without using ERXEC.&lt;br /&gt;&lt;br /&gt;New, better, implementation of SQL parsing (for executing SQL scripts).&lt;br /&gt;&lt;br /&gt;Migrations now support SQLServer (well, more than they did).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;New Frameworks&lt;/span&gt;&lt;br /&gt;WOJavaRebel framework provides support for easily running WO apps with JavaRebel for modifying classes on-the-fly without restarting.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Utilities&lt;/span&gt;&lt;br /&gt;New warnings when you are possibly misusing ERXThreadStorage.&lt;br /&gt;&lt;br /&gt;ERXEOControlUtilities. validateUniquenessOf provides a utility method for validating unique EO attribute values.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Application&lt;/span&gt;&lt;br /&gt;You can now set a low memory threshold separate from a memory starvation threshold, and both now fire notifications that you can respond to.&lt;br /&gt;&lt;br /&gt;Support for making ERXResourceManager generate complete resource URLs by setting context. _setGenerateCompleteResourceURLs.&lt;br /&gt;&lt;br /&gt;Simple resource rewriting -- Set er.extensions.ERXResponseRewriter.resource.frameworkName.filePath = newFrameworkName.newFilePath &lt;br /&gt;&lt;br /&gt;Support for forcing the removal of instance numbers from context urls via the er.extensions.ERXWOContext.forceRemoveApplicationNumber property.  You should only use this if you know what you're doing, as this can't always be used in WO.&lt;br /&gt;&lt;br /&gt;Support for SSL with DirectConnect.  Here's the pertinent docs from Properties:&lt;br /&gt;#########################################################################&lt;br /&gt;# SSL DirectConnect&lt;br /&gt;#########################################################################&lt;br /&gt;## You should probably not enable any of these settings in a normal Apache webserver deployment,&lt;br /&gt;## in particular the ssl port property, as this is used by ERX to generate https URLs, which must&lt;br /&gt;## match your Apache config.&lt;br /&gt;##&lt;br /&gt;## To enable SSL support with DirectConnect, you must do the following:&lt;br /&gt;##&lt;br /&gt;## * In your Resources folder, run "keytool -genkey -alias WebObjects -keyalg RSA -keystore adaptorssl.key".  Select a &lt;br /&gt;##   password for your keystore (i.e. "changeit"), and set the "your first name and last name" field to match the hostname &lt;br /&gt;##   that you will be running your directconnect app off of.&lt;br /&gt;## * In your Resources folder, create an executable script (it MUST BE EXECUTABLE) named "adaptorsslpassphrase" with the&lt;br /&gt;##   contents:&lt;br /&gt;##   echo changeit&lt;br /&gt;##   where you should replace "changeit" for whatever password you selected in the previous step.&lt;br /&gt;## * Set the following property to true&lt;br /&gt;#er.extensions.ERXApplication.ssl.enabled=true&lt;br /&gt;&lt;br /&gt;## (optional) To specify an SSL host name other than what is returned from a call to&lt;br /&gt;## application.host(), you can override it below  &lt;br /&gt;#er.extensions.ERXApplication.ssl.host=localhost&lt;br /&gt;&lt;br /&gt;## (optional) To select an SSL port other than 443, uncomment the following. If you are already running Apache with SSL,&lt;br /&gt;## you probably want to set this.  If the port number is 0, the SSL port will be automatically assigned (using the same&lt;br /&gt;## mechanism that WO uses to set the regular port) &lt;br /&gt;#er.extensions.ERXApplication.ssl.port=0&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;OGNL&lt;/span&gt;&lt;br /&gt;New click-to-debug feature.  When ognl.debugSupport=true, the WOLips Toolbar has a new Click to Debug option that will turn on binding debug information for any component that you click on.  This is really useful if you're trying to track down a rogue binding.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-503435827705554512?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/xqCMBW9U8ok" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/503435827705554512/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/12/this-week-in-wonder.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/503435827705554512?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/503435827705554512?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/xqCMBW9U8ok/this-week-in-wonder.html" title="This Week in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/12/this-week-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04GRHY6fCp7ImA9WxRUE08.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-2780394028472208513</id><published>2008-11-21T22:41:00.000-05:00</published><updated>2008-11-21T22:52:05.814-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-21T22:52:05.814-05:00</app:edited><title>These 49 Days in Wonder</title><content type="html">&lt;span style="font-weight:bold;"&gt;General&lt;/span&gt;&lt;br /&gt;All Project Wonder projects were switched to the WOLips Nightly's new hotness build path system.  This means that to checkout the Wonder source now requires that you use a WOLips Nightly build, though these are pretty likely to turn into stable pretty soon.&lt;br /&gt;&lt;br /&gt;We cleared a lot of the backlog of patches in Jira ... Sorry it took us so long.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;Ajax framework was updated to &lt;a href="http://prototypejs.org/2008/9/30/prototype-1-6-0-3-one-more-bugfix-release-before-1-6-1"&gt;Prototype 1.6.0.3&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;AjaxSocialNetwork and AjaxSocialNetworkLink provides support for submitting URLs to a heap of social linking sites using their recommended icons&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Components&lt;/span&gt;&lt;br /&gt;ERXEmbeddedPage and ERXSwitchEmbeddedPage allow you to wrap a section of your page and treat return values from invokeAction as a replacement only for the this element and not for the entire page. This allows you to write components that operate like a sequence of top level elements, yet actually they live within a larger page.&lt;br /&gt;&lt;br /&gt;ERXAccessibleSubmitButton provides support for defining hot keys for submit buttons.&lt;br /&gt;&lt;br /&gt;ERXJSToManyRelationshipEditor provides a nice javascript-based to-many relationship editor&lt;br /&gt;&lt;br /&gt;ERXBooleanPopUpButton provides a simple Yes/No/All (labels configurable) three-state popup button that binds out a Boolean value, which is handy for boolean search filters&lt;br /&gt;&lt;br /&gt;ERXRedirect supports redirecting to a stateful component (in addition to several other variants).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;EOF&lt;/span&gt;&lt;br /&gt;New "javaEnum" prototype ... Select it and just set the valueClassName to point to your java Enum class.&lt;br /&gt;&lt;br /&gt;Lots of fixes for Oracle in the EROraclePlugin including many fixes to make Wonder's ERXMigration API work properly.  The Oracle plugin also has a new delegate that allows you to provide a custom constraint name generator (to provide custom truncation rules).&lt;br /&gt;&lt;br /&gt;FrontBase, Postgresql, and Oracle plugins now automatically correct the EOF bug with generating "not null" columns for attributes that only appear in subclasses of single table inheritance tables.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERExtensions&lt;/span&gt;&lt;br /&gt;Added ERXSession support for requiring secure session cookies to prevent session hijacking.&lt;br /&gt;&lt;br /&gt;ERXEnterpriseObjectCache now supports optionally caching EO's rather than just their GID's, lazily filling the cache rather than preloading the entire set of objects, and caching with a qualifier (i.e. only cache objects where published=true)&lt;br /&gt;&lt;br /&gt;ERXYahooContentAnalysisService connects to Yahoo's term extraction service (for use with auto-tagging)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc&lt;/span&gt;&lt;br /&gt;Lots of fixes to ERRest framework, including many changes necessary to be able to generate a validating schema for a rest document (the schema generator is not yet committed).  Lots of additional enhancements to run ERRest documents without a request, which makes it easier to use for data loading.&lt;br /&gt;&lt;br /&gt;WOOgnl no longer requires a different source path for 5.3 and 5.4, though it does require a different binary framework.&lt;br /&gt;&lt;br /&gt;Lots of fixes to SproutCore framework to bring it more in line with the latest SproutCore releases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-2780394028472208513?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/asWmUIM_Ca0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/2780394028472208513/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/11/these-49-days-in-wonder.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/2780394028472208513?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/2780394028472208513?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/asWmUIM_Ca0/these-49-days-in-wonder.html" title="These 49 Days in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/11/these-49-days-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQGSH88fyp7ImA9WxRQEEo.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-4190804567072836056</id><published>2008-10-03T19:29:00.000-04:00</published><updated>2008-10-03T19:58:49.177-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-03T19:58:49.177-04:00</app:edited><title>This Belated Week in Wonder</title><content type="html">Yeah.  It's been a few weeks.  I know .... Better late than never:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;AjaxExpansion - If you've ever tried to make a component that has a triangle (or whatever) that you can turn down to show additional information, you know it's actually a little tricky to build that component and make it animate nicely with a slide down effect. AjaxExpansion makes this easy to do and there is an addition to the AjaxExample2 ToggleDetails example that shows how to use it.&lt;br /&gt;&lt;br /&gt;By popular demand, AjaxTabbedPanel can now hide tabs.&lt;br /&gt;&lt;br /&gt;AjaxUpdateLink, AjaxSubmitButton, and AjaxObserveField now support updateContainerID="_parent", which will update the nearest ancestor component AjaxUpdateContainer.  This makes it so you don't have to pass id's around in the common case that you're just updating your parent container.&lt;br /&gt;&lt;br /&gt;There's a new example of using AjaxModalContainer in AjaxExample2.&lt;br /&gt;&lt;br /&gt;Chuck fixed tons of weird little border cases.&lt;br /&gt;&lt;br /&gt;AjaxModalDialog is now in ... It's a competitor to AjaxModalContainer based on the modalbox Javascript library, but is designed to have a slightly nicer component backend that can track the open state on the server side (which allows for fancier component content).  There's a new AjaxExample that shows this in action.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERExtensions&lt;/span&gt;&lt;br /&gt;ERXExceptionUtilities provides a bunch of handle methods for printing and handling stack traces, including stack trace filtering that tries to hide all those nasty looking WO/EOF stack frames.  See &lt;a href = "http://webobjects.mdimension.com/wonder/api/er/extensions/foundation/ERXExceptionUtilities.html"&gt;the javadoc&lt;/a&gt; for more info.  Also, you can set your log appender to  er.extensions.logging.ERXConsoleAppender to get stack trace filtering wired into all of your log4j output.  Check out StackTraceSkipPatterns-Normal.plist in ERExtensions/Resources to see how you can provide your own stack trace filtering extensions.&lt;br /&gt;&lt;br /&gt;ERXApplication can now load Properties from inside of jar frameworks.&lt;br /&gt;&lt;br /&gt;multipleSubmit=true is now defaulted on for all WOForms.  Rest in peace stupid binding.&lt;br /&gt;&lt;br /&gt;ERXLazyValue provides a way to model lazy-loaded values that invalidate with different methods. This is very useful for storing expensive values that are returned from bound component methods as well as values that are cached that are influenced by different areas of a single page (i.e. ajax operations on one part of the page that need to invalidate a cache on another part of the page).&lt;br /&gt;&lt;br /&gt;ERXDisplayGroup now uses generics.&lt;br /&gt;&lt;br /&gt;ERXKey now uses generics in all of the .is(..) etc methods.&lt;br /&gt;&lt;br /&gt;ERXWOComponentContent is now a little bit slicker and supports the concept of a "default" template.  If you define an ERXWOComponentContent with no template name, it will find all of the component content children that are not contained inside of an ERXWOTemplate and treat them as if they were in a default component content.&lt;br /&gt;&lt;br /&gt;There's an NSBundle replacement in Wonder now.  This fixes a bug with jar loading in embedded frameworks that would end up loading in the application bundle, which causes the very common bug of getting a Session class that isn't your Session.  This is also provides some support for making launching non-WOApplication WO things (like EOF main methods) in WOLips a little smarter.&lt;br /&gt;&lt;br /&gt;ERXFetchSpecification has a new setIncludeEditingContextChanges(boolean) option.  When true, fetching with this fetch spec will call through ERXEOControlUtilities.objectsWithQualifier and also process the new (uncommitted) changes from your EC.  For instance, if you have inserted EO's into your EC, includeEditingContextChanges = true will cause those new EO's to be included in the results of the fetch.  Likewise, updated, deleted, and parent EC objects will be processed accordingly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERPrototypes&lt;/span&gt;&lt;br /&gt;New IP Address prototype (along with new migration methods to support it).&lt;br /&gt;&lt;br /&gt;New byte24 prototype for generating guid PKs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt;&lt;br /&gt;Both the 5.3 and 5.4 version of Wonder can be now be built with Maven.  Talk to Henrique for more info :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERAttachment&lt;/span&gt;&lt;br /&gt;You can now register a &lt;a href = "http://webobjects.mdimension.com/wonder/api/er/attachment/processors/IERAttachmentProcessorDelegate.html"&gt;custom delegate&lt;/a&gt; onto your ERAttachmentProcessors to be notified of various events in the attachment lifecycle.  This allows your application to perform additional operations in response to those events.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-4190804567072836056?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/tUIem_jATSI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/4190804567072836056/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/10/this-belated-week-in-wonder.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4190804567072836056?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4190804567072836056?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/tUIem_jATSI/this-belated-week-in-wonder.html" title="This Belated Week in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>6</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/10/this-belated-week-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQAQ307cSp7ImA9WxdaFE4.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-8142762169299589056</id><published>2008-08-22T15:19:00.000-04:00</published><updated>2008-08-22T15:45:42.309-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-22T15:45:42.309-04:00</app:edited><title>This Week in Wonder</title><content type="html">&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;The AjaxExample2 app has been committed to Wonder.  This is the application that was shown during the Ajax session at WOWODC 2008.  Whereas AjaxExample shows off many features of the framework but not with real-world examples, AjaxExample2 takes the approach of trying to show the framework off in the context of solving real interface problems.&lt;br /&gt;&lt;br /&gt;ibox.js in AjaxModalContainer was updated to 2.17b&lt;br /&gt;&lt;br /&gt;You no longer have to iBox.init() at the end of your AjaxUpdateContainers when you generate new AjaxModalContainers in ajax responses.  This all "just works" now.&lt;br /&gt;&lt;br /&gt;AjaxModalContainer has a new locked flag that disallows closing and an open flag that forces it open (rather than waiting for a click).&lt;br /&gt;&lt;br /&gt;AjaxModalContainer works with HTTPS URLs now.&lt;br /&gt;&lt;br /&gt;New AjaxUtils.arrayValueForBinding utility method, which supports loading array bindings that are defined as references to NSArray as well as inline JSON-syntax Strings.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Migrations&lt;/span&gt;&lt;br /&gt;ERXMigrationTable provides a newLargeStringColumn method that corresponds roughly to the varcharLarge prototype in Wonder.  This helps to abstract out the weird big column width you'd previously have to define in your migrations for those columns and hopefully makes this more database independent.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;EOF&lt;/span&gt;&lt;br /&gt;ERXModelGroup checks for a subtle problem that is probably more common than people might think where your connection dictionaries across multiple models aren't EXACTLY the same, which results in EOF treating them like different databases.  Now this will generate an exception at startup.&lt;br /&gt;&lt;br /&gt;ERXJDBCConnectionBroker has a new fix for a resource contention problem with leaving connections in an incorrect state.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;FrontbasePlugIn&lt;/span&gt;&lt;br /&gt;You can now set com.frontbase.unique.[ModelName].[EntityName]=xxx, com.frontbase.unique.[ModelName]=xxx, or com.frontbase.unique=xxx to specify the initial unique value that is used by the FrontBasePlugIn when it generates sequences.  I don't think EntityModeler will pick this up, but if you're using migrations, you'll get it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Components&lt;/span&gt;&lt;br /&gt;Ravi Mendis has committed fixes for XHTML compliance in several components.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc&lt;/span&gt;&lt;br /&gt;ERXResponse supports pushing and popping response content on a stack.  This is interesting if you want to post process the output of a single component in isolation from the rest of the response (but you want to maintain all the other state of the response).&lt;br /&gt;&lt;br /&gt;ERXExtensions.initApp and ERXExtensions.initEOF should be a little easier to use now.  In your JUnit TestSuites, you can just add a static method:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;static {&lt;br /&gt;    ERXExtensions.initApp(Application.class, new String[0]);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;and you will be running your test case in a full Wonder-ful Application environment.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERIUI&lt;/span&gt;&lt;br /&gt;If you've ever tried out the iui css + js for making iPhone apps, you may have noticed that it is a complete disaster for connecting to component-action-based WO apps.  The Javascript presumes stateless URLs and eventually will explode.  ERIUI takes the base CSS work from iui but with a completely rewritten Javascript layer that provides much richer stateful component-based interactions with your app.  The docs are severely lacking on this one at the moment (this was just a hobby framework for me).  To get good performance on the phone, the framework uses WebKit CSS animations (which currently only works in the WebKit nightlies, not in Safari 3.x), though it "gracefully" degrades (to no animation) on the desktop.  Checkout ERIUIExample to see it in action ... This should be considered "preview" quality for now.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Google Chart&lt;/span&gt;&lt;br /&gt;There's a new GoogleChart framework for generating charts via the Google Chart API.  This is inspired (quite a bit) by the Ruby googlecharts framework.  There's &lt;a href = "http://webobjects.mdimension.com/wonder/api/er/googlechart/package-summary.html"&gt;more info here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-8142762169299589056?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/cyepFdXKtoY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/8142762169299589056/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/08/this-week-in-wonder.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/8142762169299589056?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/8142762169299589056?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/cyepFdXKtoY/this-week-in-wonder.html" title="This Week in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/08/this-week-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYGQ3g-eSp7ImA9WxdbEkg.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-1033853823422062782</id><published>2008-08-08T23:23:00.000-04:00</published><updated>2008-08-09T00:28:42.651-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-09T00:28:42.651-04:00</app:edited><title>These 9 Weeks in Wonder</title><content type="html"> Yeah, I know, long time no write ... Occasionally Real Work (TM) gets in the way.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Migrations&lt;/span&gt;&lt;br /&gt;newLocalizedStringColumn supports creating string columns that work with Wonder's localized attributes ("name_en," "name_de," etc).&lt;br /&gt;&lt;br /&gt;Migration support for dropping composite pks (though the FrontBase plugin doesn't actually support this :( ).&lt;br /&gt;&lt;br /&gt;BigInteger column support.&lt;br /&gt;&lt;br /&gt;newFlagBooleanColumn which generates a Types.BOOLEAN column instead of a varchar(5) or int boolean column.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERIndexing&lt;/span&gt;&lt;br /&gt;Updated to Lucene 2.3.2.&lt;br /&gt;&lt;br /&gt;ERIndexingExample is a new example app that shows how to use ERIndexing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERCaching&lt;/span&gt;&lt;br /&gt;More work on memcached integration, though I think (correct me if I'm wrong, Anjo?) it's not quite ready for primetime yet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERSelenium&lt;/span&gt;&lt;br /&gt;StandaloneRunner supports running Selenium tests from the commandline.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;SproutCore&lt;/span&gt;&lt;br /&gt;Initial work on supporting the development of SproutCore applications with WO.  Currently the work on SproutCore has been replacing the rails-based templating system with a WO-based templating system.  While not necessarily required for developing SC apps, it provides nicer integration with existing tools.  Currently you can run the WO-equivalent of several of the SC example apps in live mode ..... mostly :)  This is to be considered very experimental right now.&lt;br /&gt;&lt;br /&gt;Check out the SproutCoreExample app to see it in action.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Wonder 2.0&lt;/span&gt;&lt;br /&gt;We're on Wonder 5.0, but iTunes has lots of miscellaneous enhancements to their Wonder 2.0 fork.  Thanks to the iTunes folks, all the enhancements that live in 2.0 are now moving up to the trunk.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JSON&lt;/span&gt;&lt;br /&gt;Lots of work on JSON support in Ajax framework.&lt;br /&gt;&lt;br /&gt;You can now optionally include attributes and relationships in your JSON results via the client class property setting in your model.&lt;br /&gt;&lt;br /&gt;You can specify writable vs read-only attributes.&lt;br /&gt;&lt;br /&gt;Marshalling/unmarshalling of EOTemporaryGlobalIDs is supported, so you can pass around uncommitted EO's to/from the server.&lt;br /&gt;&lt;br /&gt;There is now support in the client API's for converting full EO's to EO stubs as a performance enhancement when passing to API's that only require an EO's id (the server side faults it back in for you).&lt;br /&gt;&lt;br /&gt;Support for custom EO serializers.  For instance, you can add the custom serializer for ERAttachments by calling JSONRPCBridge.getSerializer().registerSerializer(new ERAttachmentObjectSerializer()), which will inject the attachmentUrl into the JSON object during serialization so your client can simply refer to the attachment without doing another round-trip.&lt;br /&gt;&lt;br /&gt;JSONComponents are an experiment in trying to rethink web services in the language of WOComponents.  JSON service endpoints can now return JSONComponents, which are stateful service endpoints.  This allows for cleaner encapsulation of your services while also allowing the server to make decisions on the routing path through your service as well as the services themselves being stateful.  For instance, clients can call the login method of the authentication service, which can return back the next service to talk to, and just like WOComponents, repeated calls to the component return to the correct state on the server.  The end result is actually a bit like PDO ... JSONComponent are to Component Actions as traditional WOWebServices are to DirectActions.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERAttachment&lt;/span&gt;&lt;br /&gt;ERAttachment URLs are now a little smarter and more optimized in that the URL can now include the PK of the attachment being requested.  It still verifies the provided webpath for security, but the server can almost always avoid an extra fetch by attempting to fault the PK rather than fetch by webpath.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERExtensions&lt;/span&gt;&lt;br /&gt;ERXRemoteNotificationCenter provides support for posting arbitrary notifications across multiple servers.  Provides a simple implementation as well as a JGroups implementation.&lt;br /&gt;&lt;br /&gt;ERXIFrame can act as a component for simply creating an iframe to a URL, or more interestingly can render its component content as the iframe contents, which is really handy.&lt;br /&gt;&lt;br /&gt;ERXPartialMarker/ERXPartialWrapper is crazy, but if I understand it properly, it provides support for rendering one section of your page that will appear in another section of your page.  It's currently used by the SproutCore framework.&lt;br /&gt;&lt;br /&gt;ERXFlashMovie is just a handy wrapper around embedding an SWF in a page.&lt;br /&gt;&lt;br /&gt;ERXEOGlobalIDUtilities does a lot more work to make sure that it doesn't refetch objects that were already faulted.&lt;br /&gt;&lt;br /&gt;ERXQ.containsObject.  If you're a fan of the "contains" qualifier selector, you'll be a fan of this method.&lt;br /&gt;&lt;br /&gt;ERXRecursiveBatchFetching is a terrible name.  It's now named ERXBatchFetchUtilities. The old class extends the new class and is marked @deprecated.  ERXBatchFetchUtilities also now provides several batch fetching variants based on ERXKey.&lt;br /&gt;&lt;br /&gt;ERXDatabaseContextMulticastingDelegate now supports both 5.3 and 5.4.&lt;br /&gt;&lt;br /&gt;ERXTemporaryGlobalID provides many of the benefits of 24-byte GUID PKs without the annoyance of byte[] PKs in your database by "fitting" a GUID into a long-sized value.&lt;br /&gt;&lt;br /&gt;ERXEOControlUtilities.convertEOtoGID and convertGIDtoEO now support non-EO objects that contain EOs (for instance, a pojo proxy object that wraps an EO) via the IERXEOContainer and IERXGIDContainer interfaces.&lt;br /&gt;&lt;br /&gt;ERXMutableURL is a little smarter about not generating :80's for http and :443's for https.&lt;br /&gt;&lt;br /&gt;ERXEOAccessUtilities.createRelationship and createFlattenedRelationship provide easier methods for programatically mucking with your EOModels&lt;br /&gt;&lt;br /&gt;ERXEOControlUtilities.distinctValuesForKeyPath will give you an array of the distinct values of a particular keypath on an entity.&lt;br /&gt;&lt;br /&gt;ERXModernNavigationMenu/Item provides an upgraded replacement of ERXNavigationMenu/item that are CSS and semantic markup instead of the older table-based layout.&lt;br /&gt;&lt;br /&gt;ERXArrayChooser now supports arbitrary qualifiers and fetching of shared objects.&lt;br /&gt;&lt;br /&gt;ERXModuloQualifier can generate SQL queries that use the "mod" keyword.&lt;br /&gt;&lt;br /&gt;ERXFetchSpecificationBatchIterator now supports prefetching and raw rows.&lt;br /&gt;&lt;br /&gt;ERXGenericRecord will now cache its primary key rather than constantly regenerate.&lt;br /&gt;&lt;br /&gt;ERXJobLoadBalancer "solves the following problem:  we have a set of jobs (identified by an Id) waiting to be processed. Several worker processes are competing for jobs and we need to way to efficiently parcel out those jobs out. We want to avoid as much as possible several workers attempting to grab the same jobs and locking it."  This works across instances, by the way.  It's works sort of like Xgrid.  The new version of ERMailer coming from Wonder 2.0 will use this class to load balance sending email across multiple instances/apps.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;AjaxObserveField has a new onCreate option that is called after form serialization, but prior to form submission, which allows you to do things like disabling the form while it's sending in the background.&lt;br /&gt;&lt;br /&gt;Better compatibility with FireFox 3's more aggressive caching of Ajax requests.&lt;br /&gt;&lt;br /&gt;AjaxModalContainer supports binding "action" even when ajax=true, so you can perform a component action prior to rendering the component content of your container.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;BugTracker&lt;/span&gt;&lt;br /&gt;BugTracker now include support for the audit trails.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt;&lt;br /&gt;Lots of work on the maven build files for Wonder.  As I understand it, which I don't :), Wonder Maven builds "just work".&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WO Adaptors&lt;/span&gt;&lt;br /&gt;Q updated all the WO adaptors in Wonder.  The 5.4 enhancements are merged with the Wonder enhancements.  The build files have all been cleaned up, FreeBSD support was added, and several fixes went into the FastCGI adaptor.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERRest&lt;/span&gt;&lt;br /&gt;ERXUnsafeRestEntityDelegate can now be optionally enabled in production.  This is handy if your restful service is behind authentication and only used for administrative services where ACLs are not an issue.&lt;br /&gt;&lt;br /&gt;ERXAbstractRestEntityDelegate subclasses can more easily provide support for custom "primary keys" to be generated and resolved by overriding _isEOID, _objectWithKey, and idForEO methods.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-1033853823422062782?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/armzm_CBXsw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/1033853823422062782/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/08/these-9-weeks-in-wonder.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/1033853823422062782?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/1033853823422062782?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/armzm_CBXsw/these-9-weeks-in-wonder.html" title="These 9 Weeks in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/08/these-9-weeks-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAGRn8zcCp7ImA9WxdUE04.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-7465300727785750735</id><published>2008-07-29T08:15:00.001-04:00</published><updated>2008-07-29T08:15:27.188-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-29T08:15:27.188-04:00</app:edited><title>Not Dead, Just Busy</title><content type="html">&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-7465300727785750735?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/vwSfoXKbwPc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/7465300727785750735/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/07/not-dead-just-busy.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/7465300727785750735?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/7465300727785750735?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/vwSfoXKbwPc/not-dead-just-busy.html" title="Not Dead, Just Busy" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/07/not-dead-just-busy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQMRXk4eCp7ImA9WxdRGEg.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-7802471043649468770</id><published>2008-06-07T13:01:00.000-04:00</published><updated>2008-06-07T13:06:24.730-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-07T13:06:24.730-04:00</app:edited><title>This week in Project Wonder</title><content type="html">Since the move to svn, we've been able to clean things up a bit.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;New structure&lt;/span&gt;&lt;br /&gt;There are now three important top-level folders, /Applications, /Frameworks and /Examples. If you use checked-out projects, you need to close and delete these projects, then select /Frameworks and pick the ones you like. Note that - depending on what you actually use - it is WAY simpler than before, where you had to visit X subfolder for importing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Packages&lt;/span&gt;&lt;br /&gt;Also, moving stuff in ERX into packages has been a request for quite a while now. We had good reasons not to do this so far, there are numerous  thread on the lists where you can read the arguments at your leasure. But eventually we had to do it and now is as good a time as any.&lt;br /&gt;&lt;br /&gt;So: the current trunk in SVN contains the repackaged ERX and ERDirectToWeb, complete  with all fixes that are needed to build Wonder itself. In your own  apps, you should:&lt;br /&gt;&lt;br /&gt;- commit outstanding changes (!)&lt;br /&gt;- select the projects, run an "Organize imports"&lt;br /&gt;- check all your EO templates, as a lot of stuff changed packages&lt;br /&gt;- check all your logging configs. A stub ERXPatternLayout is currently  &lt;br /&gt;still in er.extensions, but it will go away soon.&lt;br /&gt;- check any xxx.className property which has a er.extensions thing in  &lt;br /&gt;it *&lt;br /&gt;- check your model for custom attributes which reference ERX classes  &lt;br /&gt;(erprototypes has been fixed)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Deployment&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;WOTaskd+JavaMonitor have been updated:&lt;br /&gt;&lt;br /&gt;- backups of SiteConfigs in /Library/WebObjects/Configuration, prior  &lt;br /&gt;to changes. The name indicates the action that happened afterwards.&lt;br /&gt;- fixed an issue with the app delete page&lt;br /&gt;- selection in app detail page is now Ajax and kept&lt;br /&gt;- JavaMonitor/wotaskd are now ERX apps with embedded frameworks&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-7802471043649468770?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/SCPjMwbMZ4o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/7802471043649468770/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/06/this-week-in-project-wonder.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/7802471043649468770?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/7802471043649468770?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/SCPjMwbMZ4o/this-week-in-project-wonder.html" title="This week in Project Wonder" /><author><name>Anjo Krank</name><uri>http://www.blogger.com/profile/12153571432284820771</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/06/this-week-in-project-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMCSH85eSp7ImA9WxdRFE0.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-6380552027735625144</id><published>2008-06-02T06:29:00.000-04:00</published><updated>2008-06-02T07:01:09.121-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-02T07:01:09.121-04:00</app:edited><title>Short break</title><content type="html">We interrupt our scheduled program for a news flash:&lt;br /&gt;&lt;br /&gt;As of Saturday, Mai 30th 2008, we moved the Wonder repository to SVN. Check out the trunk via&lt;br /&gt;&lt;br /&gt;svn co https://wonder.svn.sourceforge.net/svnroot/wonder/trunk/Wonder Wonder&lt;br /&gt;&lt;br /&gt;The CVS repository will NOT be updated any time soon.&lt;br /&gt;&lt;br /&gt;Now on with our regular schedule.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-6380552027735625144?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/H2uGRP_3lIQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/6380552027735625144/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/06/short-break.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/6380552027735625144?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/6380552027735625144?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/H2uGRP_3lIQ/short-break.html" title="Short break" /><author><name>Anjo Krank</name><uri>http://www.blogger.com/profile/12153571432284820771</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/06/short-break.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIFQX8yeip7ImA9WxdREUo.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-1065755231677307567</id><published>2008-05-30T15:48:00.000-04:00</published><updated>2008-05-30T16:15:10.192-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-30T16:15:10.192-04:00</app:edited><title>Thi(e)s(e) (2.5) Week(s) in Wonder</title><content type="html">&lt;span style="font-weight:bold;"&gt;ERCoreBusinessLogic&lt;/span&gt;&lt;br /&gt;ERCoreBusinessLogic has a nice new generic audit trail mechanism in the form of ERCAuditTrail.  More documentation to come soon on this.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERXKey&lt;/span&gt;&lt;br /&gt;Chainable sort orders via ERXSortOrder (and/or ERXKey's sort order methods).  For instance, you can do:&lt;br /&gt;&lt;br /&gt;NSArray&lt;EOSortOrdering&gt; sortOrders = Person.LAST_NAME.asc().then(Person.FIRST_NAME).asc()).array();&lt;br /&gt;&lt;br /&gt;ERXKey has "plural forms" of the sort order methods.  For instance, Person.FIRST_NAME.ascs() (the "s" on the end will give you an NSArray containing a single eosortordering that represents "firstName asc") -- this is just a sort-cut for cases where you just have a single EOSortOrdering that you want to pass to a fetch spec.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;AjaxSubmitButton can perform a partial submit without having an updateContainerID specified now (which really could be considered a bug, which I usually don't list here, but it's handy to know).  So it behaves similarly to AjaxUpdateLink and AjaxSubmitButton's without a partial submit in that it will turn into a background request only.&lt;br /&gt;&lt;br /&gt;You can now control Ajax resource insertion by providing a delegate to ERXResponseRewriter via ERXResponseRewriter.setDelegate(yourDelegate).  See &lt;a href = "http://webobjects.mdimension.com/wonder/api/er/extensions/ERXResponseRewriter.Delegate.html"&gt;ERXResponseRewriter.Delegate&lt;/a&gt;.  This lets you override when the framework (or other code) asks to include "Ajax" "prototype.js" and instead replace it for your own custom resource.  For instance, if you want to bundle all your js into a single file, you can provide a delegate that overrides requests for any of the individual files and instead use your custom ones, or replace files with a minimized version of the original which may only be used in production.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;AjaxModalContainer&lt;/span&gt;&lt;br /&gt;AjaxModalContainer got a bit of a face lift (this is quoted from my original post on wonder-disc:)&lt;br /&gt;&lt;br /&gt;Previously if you put contents inside the container tag, it would always render, which could be really big if you have a repetition.  Now you can set ajax=true, and it will fetch the contents in an Ajax request instead.  If you set ajax=true, you must also provide an id binding.&lt;br /&gt;&lt;br /&gt;Previously, all the Ajax requests that were happening were not tagged with the proper request header, so it made Ajax requests appear to the server to be non-ajax requests.&lt;br /&gt;&lt;br /&gt;There is now an iBox.init() function that is exposed to allow reinitializing iBox.  For instance, if you have iBoxes in an update  &lt;br /&gt;container, you will want to call this at the bottom of your container. We need to add a better, more generalized way, to address this problem at some point, because several of the libraries have similar requirements.&lt;br /&gt;&lt;br /&gt;You really should carefully consider the use of the action binding.  It does not execute as an Ajax request (I'm not sure why, but it's explicitly documented as such), which means you can burn your backtrack cache using it.  The preferred method of use for modal container should really be external hrefs, direct contents, or the new ajax=true binding with contents.  In fact, unless someone has an example where the action binding is valid (which is possible -- I just can't think of an example), I'm almost tempted to consider it deprecated, or at least the behavior might change to make it more like other action bindings on Ajax components.&lt;br /&gt;&lt;br /&gt;Lastly, there's a new example in ModalContainerExample that shows AjaxModalContainer used inside a repetition with an ajax=true that contains a form that allows you to edit objects in the repetition.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Migrations&lt;/span&gt;&lt;br /&gt;Migrations support more batch operations.  For instance, previously you had to call .create() on a table prior to calling .setPrimaryKey(..).  The Migration API now keeps track of whether or not it has been created and will work the same either way.  Additionally, there are some new methods on ERXMigrationTable that provide support for PK generation through the usual EOF routes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;EOF&lt;/span&gt;&lt;br /&gt;ERXQualifierInSubquery provides support for fetching objects of an entity where one of its to-many relationships matches a given qualifier.&lt;br /&gt;&lt;br /&gt;ERXJDBCUtilities has some more convenience methods for doing ResultSet manipulation (for use primarily in complex migrations) via processConnection and processResultSetRows (see the javadoc for more info on using).  Mainly these guys take care of opening and closing JDBC resources for you based on EOF adaptors.&lt;br /&gt;&lt;br /&gt;ERXKeyGlobalID provides support for serializable EOKeyGlobalID's.&lt;br /&gt;&lt;br /&gt;There is a new "globalID" prototype for storing globalID values in other EO's that uses ERXKeyGlobalID.&lt;br /&gt;&lt;br /&gt;Rather than set the 4 or 5 recommended EC locking Properties, you can now just set er.extensions.ERXEC.safeLocking=true which will set all the recommended values for you instead.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc&lt;/span&gt;&lt;br /&gt;ERXExtensions.initApp and ERXExtensions.initEOF static methods have been added to support running Wonder in test cases and  main methods without wrapping your code in ERXMainRunner or a WOApplication.&lt;br /&gt;&lt;br /&gt;ERXQuicksilverQualifier is a KeyValueQualifier that compares values with ERXStringUtilities.quicksilverContains, which considers "QS" to be 'equal' to "QuickSilver" -- matches the original string as long as the letters appear in sequence, but not necessarily contiguous.  This does _NOT_ work in EOF -- only in memory.&lt;br /&gt;&lt;br /&gt;"wo:img" and "wo:image" are now built-in shortcuts for the inline bindings parser.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-1065755231677307567?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/lCIaKBzpfOM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/1065755231677307567/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/05/thiese-25-weeks-in-wonder.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/1065755231677307567?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/1065755231677307567?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/lCIaKBzpfOM/thiese-25-weeks-in-wonder.html" title="Thi(e)s(e) (2.5) Week(s) in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/05/thiese-25-weeks-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYCSHc6fip7ImA9WxdTGUk.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-5220147514298009112</id><published>2008-05-16T10:14:00.000-04:00</published><updated>2008-05-16T10:29:29.916-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-16T10:29:29.916-04:00</app:edited><title>Last Year's Last 20 Weeks in Wonder</title><content type="html">We'll resume our regularly scheduled This Week in Wonder soon, but I had to go through all the ChangeLogs back to last year's WOWODC to figure out what I wanted to talk about at this year's WOWODC.  I thought I'd go ahead and post my notes.  There's very little detail here, but it was about 5000 lines of commit logs between June 2007 and January 2008, so these are just the ones that stood out to me.  I'm sure there's a inadvertent bias towards thing I worked on (and things at the beginning of the list when I wasn't yet totally annoyed by changelogs).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;5.4&lt;/span&gt;&lt;br /&gt;* Lots of 5.4 compatibility work&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;* AjaxPing - support very small Ajax poller that can refresh a larger container when the cache key changes&lt;br /&gt;* AjaxInPlace - added support for link vs button submits + better support for being in an existing form&lt;br /&gt;* AjaxLongResponse&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Components&lt;/span&gt;&lt;br /&gt;* ERXClickableContainer - makes arbitrary elements into links&lt;br /&gt;* ERXWORepetition EO support - if er.extensions.ERXWORepetition.eoSupport=true, GIDs will be used instead of hashcodes&lt;br /&gt;* ERXFlickrBatchNavigation/AjaxFlickrBatchNavigation&lt;br /&gt;* ERXComponent - handy component baseclass&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Deployment&lt;/span&gt;&lt;br /&gt;* Wonder has slurped up JavaMonitor and wotaskd&lt;br /&gt;* Lots of enhancements to JavaMonitor&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;EOF&lt;/span&gt;&lt;br /&gt;* ERXJDBCConnectionAnalyzer (from GVC) to help debug when you have a connection problem&lt;br /&gt;* Support for ordering adaptor operations (to support SQLServer)&lt;br /&gt;* Put a nail in the coffin of editing context locking&lt;br /&gt;* FrontBasePlugIn - predictable/stable constraint names (for use in migrations)&lt;br /&gt;* Partial Entities (experimental) - &lt;a href = "http://webobjects.mdimension.com/wonder/api/er/extensions/partials/package-summary.html"&gt;more info&lt;/a&gt;&lt;br /&gt;* JavaMemoryAdaptor - an in-memory "database" ... really handy for example apps and test cases&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERSelenium&lt;/span&gt;&lt;br /&gt;* LOTS of enhancements&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Migrations&lt;/span&gt;&lt;br /&gt;* New ERXMigration baseclass for migrations that use SQL scripts&lt;br /&gt;* Support for vendor-specific SQL scripts in script migrations&lt;br /&gt;* ERXModelVersion is a top level class now&lt;br /&gt;* Added new API-based migrations - ERXMigrationDatabase, ERXMigrationTable, ERXMigrationColumn&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Qualifiers&lt;/span&gt;&lt;br /&gt;* ERXFullTextQualifier (if your database supports it)&lt;br /&gt;* ERXQ - shortcut methods for lots of different ways of creating qualifiers&lt;br /&gt;* ERXS - shortcut methods for lots of different ways of creating sort orderings&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WOOGNL&lt;/span&gt;&lt;br /&gt;* Added support for // VALID on inline bindings&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc&lt;/span&gt;&lt;br /&gt;* New pluralizer for ERXLocalizer (ported from Rails)&lt;br /&gt;* iPhone support in ERXBrowser&lt;br /&gt;* Support for multiple connections in ERIMAdaptor&lt;br /&gt;* Redesigned ERXCrypto to allow pluggable encryption algorithms &lt;br /&gt;* Added support for encrypted properties&lt;br /&gt;* ERXMutableURL&lt;br /&gt;* ERXExpiringCache supports version numbers in addition to timeouts&lt;br /&gt;* ERXStats / ERXStatisticsPage - much more powerful stats tracking&lt;br /&gt;* Refuse new sessions on low memory&lt;br /&gt;* ERXResourceManager supports WebServerResource versioning to control browser caching&lt;br /&gt;* Finally a SINGLE Properties setting for default encoding - er.extensions.ERXApplication.DefaultEncoding&lt;br /&gt;* Lots of enhancements to RuleModeler&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;New: ERAttachment.framework&lt;/span&gt;&lt;br /&gt;Inspired by th attachment_fu rails gem. Provides drop-in support for attachments that can be easily stored locally as static resource, locally as proxied resources via a custom request handler, as in-database resources (not currently streamed out of the database, so this should really only be used for person icons and other small resources), or on S3 as remote resources.  See &lt;a href = "http://webobjects.mdimension.com/wonder/api/er/attachment/package-summary.html"&gt;package.html&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;ERAttachment, btw, might be my favorite framework in Wonder ... If you use in-database attachments, you're talking add one relationship to your entity and a almost-no-code migration, then drop an ERAttachmentUpload component in your edit page, and an ERAttachmentViewer in your view page, and that's it.  Very high bang-for-the-buck.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;New: ERChronic.framework&lt;/span&gt;&lt;br /&gt;Natural language date parsing (well, assuming your "natural language" is English).  Direct port of Chronic from ruby (see &lt;a href = "http://chronic.rubyforge.org/"&gt;http://chronic.rubyforge.org/&lt;/a&gt; and &lt;a href = "http://webobjects.mdimension.com/wonder/api/er/chronic/package-summary.html"&gt;package.html&lt;/a&gt; for more details).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;New: ERCaching.framework&lt;/span&gt;&lt;br /&gt;Support for memcached with WO.  I don't actually use this one yet, so Anjo can fill in more info here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-5220147514298009112?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/6rBnGBaJvtM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/5220147514298009112/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/05/last-years-last-20-weeks-in-wonder.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/5220147514298009112?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/5220147514298009112?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/6rBnGBaJvtM/last-years-last-20-weeks-in-wonder.html" title="Last Year's Last 20 Weeks in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/05/last-years-last-20-weeks-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MMQn8zcSp7ImA9WxdTE0U.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-4646127119082630299</id><published>2008-05-09T23:00:00.001-04:00</published><updated>2008-05-09T23:18:03.189-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-09T23:18:03.189-04:00</app:edited><title>This Week in Wonder</title><content type="html">Not the most exciting Week in Wonder, but they can't ALL be awesome :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;BugTracker&lt;/span&gt;&lt;br /&gt;Attachments in BugTracker are now based on ERAttachments, and ERTags support has been added.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Migrations&lt;/span&gt;&lt;br /&gt;Migrations now support creating blob columns without specifying a size (it appears most databases don't require it).&lt;br /&gt;&lt;br /&gt;Migrations should work much more reliably with Derby.&lt;br /&gt;&lt;br /&gt;Unique index declarations for Migrations now support passing the index length, which is necessary to support indexes on MySQL (which cannot exceed certain lengths).&lt;br /&gt;&lt;br /&gt;Certain Migrations are now declared to be optional, meaning a failure of the plugin to generate SQL will not result in an exception, but instead a log error.  Foreign keys is an example, as not all database support foreign key constraints, but it's not really a failure condition.&lt;br /&gt;&lt;br /&gt;Migrations now support adding regular indexes (rather than just unique indexes).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERAttachments&lt;/span&gt;&lt;br /&gt;ERAttachments was converted from SQL-script-based migrations to api-based migrations.  This should allow it to have much better support for other databases in the future.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;AjaxObserveField has a new "observeDelay" binding that gives better periodic refresh behavior.  This is particularly useful for textfields so that it doesn't fire as often as it would with just the regular frequency setting.  With frequency, if a change occurred within the frequency period, a request will fire.  WIth observeDelay, the request will only fire after the specified observeDelay amount of idle time.  So as long as you're typing, it won't fire.  When you pause, it will then fire.&lt;br /&gt;&lt;br /&gt;If you spell the name of an update container ID wrong, you will now get a javascript error from your update links and submit buttons telling you the specified update container could not be found rather than just getting an update with no response.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Batch Fetching&lt;/span&gt;&lt;br /&gt;ERXBatchingDisplayGroup and ERXRecursiveBatchFetching have much better batch fetching behavior for to-one relationships to abstract entities (read: it works now vs ... it didn't before).&lt;br /&gt;&lt;br /&gt;ERXBatchingDisplayGroup now supports defining and using prefetching relationship key paths.&lt;br /&gt;&lt;br /&gt;ERXBatchingDisplayGroup now supports overriding the row count manually.  If you have a better method of setting the number of rows in the results compared to the display group's, you can now set it yourself.  For instance, if you know you're only ever going to fetch two pages, you could set your row count to page size * 2 and the display group will 1) not fetch more than the row count you set and 2) skip executing the count(*) query, which can potentially be expensive.  If you guess too high, it will correct for you when it runs out of rows.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;OGNL&lt;/span&gt;&lt;br /&gt;Previously in OGNL, if you declared a helper function on a keypath and one of the elements of that keypath evaluated to null, WOOGNL was not able to identify which helper class to use.  For instance, if you bound your value to "person.company.name|dosomething" and person was null, it would not know to use StringHelper.dosomething(..).  Now when this happens, it will walk the keypath to figure out what classes are in use and properly pass a null to your helper function.  This allows you to make helpers that can do null replacement (similar to valueWhenEmpty on WOString, but in the general case).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc&lt;/span&gt;&lt;br /&gt;Instead of using ERXKey.append, you can now use ERXKey.dot, which makes sense when you read your code out loud, but more importantly it's three characters shorter, which is kind of nice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-4646127119082630299?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/G6mBY81yqYM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/4646127119082630299/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/05/this-week-in-wonder.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4646127119082630299?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4646127119082630299?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/G6mBY81yqYM/this-week-in-wonder.html" title="This Week in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/05/this-week-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4DQnw9eyp7ImA9WxZaGE8.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-6269207218978799518</id><published>2008-05-03T11:35:00.000-04:00</published><updated>2008-05-03T11:36:13.263-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-03T11:36:13.263-04:00</app:edited><title>FishEye</title><content type="html">Atlassian has provided a hosted FishEye for Project Wonder at &lt;a href = "http://fisheye1.cenqua.com/browse/wonder/"&gt;http://fisheye1.cenqua.com/browse/wonder/&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-6269207218978799518?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/BxHLBCYS8yY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/6269207218978799518/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/05/fisheye.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/6269207218978799518?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/6269207218978799518?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/BxHLBCYS8yY/fisheye.html" title="FishEye" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>5</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/05/fisheye.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8DSXo8cCp7ImA9WxZaGE8.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-4709495011728294484</id><published>2008-05-03T11:26:00.000-04:00</published><updated>2008-05-03T11:34:38.478-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-03T11:34:38.478-04:00</app:edited><title>This Belated Week in Wonder</title><content type="html">&lt;span style="font-weight:bold;"&gt;EOF&lt;/span&gt;&lt;br /&gt;If you use databases sequences for PK generation that have an increment greater than one, you can now set er.extensions.ERXPrimaryKeyBatchSize or entity.userInfo.ERXPrimaryKeyBatchSize and Wonder will automatically provide a high-low implementation in memory.  This can be a big performance gain for insert-intensive applications.&lt;br /&gt;&lt;br /&gt;This was actually last week, but I forgot to mention it.  Sometimes in migrations, you have to drop down and perform JDBC operations.  A common one is adding a column and needing to set computed values for those rows.  ERXJDBCUtilities.processResultSet can make this a little bit easier:&lt;br /&gt;&lt;pre style = "overflow: scroll; white-space: nowrap"&gt;&lt;br /&gt;ERXJDBCUtilities.processResultSet(channel, "select id from SomeTable", new ERXJDBCUtilities.IResultSetDelegate() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;public void processRow(EOAdaptorChannel rsChannel, ResultSet rs) throws Exception {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int id = rs.getInt("id");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ERXJDBCUtilities.executeUpdate(rsChannel, "update SomeTable set uuid = '" + something + "' where id = " + id);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There is now a longInt prototype added to ERPrototypes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Qualifiers&lt;/span&gt;&lt;br /&gt;ERXQ and chainable qualifiers now have qualifier.one(array) which will return the single object that matches the qualifier (or null if missing) or qualifier.requiredOne(array), which will do the same but throw an exception if it's not there.  Additionally, you can call the variant qualifier.first(array), which will return the first object in the array (or null if there isn't one).&lt;br /&gt;&lt;br /&gt;All qualifiers in Wonder now are chainable qualifiers.&lt;br /&gt;&lt;br /&gt;ERXQ now provides the new shortcut methods .matches(..) (for regex qualification), .has(..) and .hasAtLeast(..) (for toMany qualifiers).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Properties&lt;/span&gt;&lt;br /&gt;Often I find that it would be nice to not have my Properties defined inside my application bundle (so deployment of a new version is easier), but defining them in JavaMonitor can also be sort of annoying.  Wonder now provides support for loading "machine global" properties.  The default location for these Properties is /etc/WebObjects/[YourAppName]/Properties .  You can change this default by setting er.extensions.ERXProperties.machinePropertiesPath .&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERRest&lt;/span&gt;&lt;br /&gt;There were a bunch of extensions and additions to ERRest so that it can be used as an EO simple syncing framework.  It's not designed to handle conflict resolution (yet), but if you have multiple applications or deployments that need to all share a common set of EO's, ERRest makes it relatively easy to do this.  For syncing, you should either be using UUID PK's or there should be a globally unique attribute on your EO.  You setup your master side just like a normal REST setup (except that you should set ERXRest.YourEntity.id=globallyUniqueAttributeName -- like ERXRest.Person.id=uuid).  On the client, you can write:&lt;br /&gt;&lt;pre style = "overflow: scroll; white-space: nowrap"&gt;&lt;br /&gt;EOEditingContext editingContext = ERXEC.newEditingContext();&lt;br /&gt;&lt;br /&gt;ERXDefaultRestDelegate restDelegate = new ERXDefaultRestDelegate();&lt;br /&gt;restDelegate.addDelegateForEntityNamed(new ERXUnsafeRestEntityDelegate(true), YourEntity1.ENTITY_NAME);&lt;br /&gt;restDelegate.addDelegateForEntityNamed(new ERXUnsafeRestEntityDelegate(true), YourEntity2.ENTITY_NAME);&lt;br /&gt;...&lt;br /&gt;ERXRestContext restContext = new ERXRestContext(context(), editingContext, restDelegate);&lt;br /&gt;&lt;br /&gt;String restPath = "Person";&lt;br /&gt;URL remoteUrl = new URL("http://remotesite/rest/" + restPath + ".xml");&lt;br /&gt;String contentStr = ERXFileUtilities.stringFromURL(remoteUrl);&lt;br /&gt;ERXRestRequest restRequest = new ERXXmlRestRequestParser().parseRestRequest(restContext, contentStr, restPath);&lt;br /&gt;ERXRestKey restResponse = restDelegate.process(restRequest, restContext);&lt;br /&gt;&lt;br /&gt;editingContext.saveChanges();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This will sync all Person entities.  You can sync arbitrary rest paths as well.  For instance, in the example above, you could just as easily use a restPath of "Person/1231-23523-blah123234531-blah" to sync an individual person.&lt;br /&gt;&lt;br /&gt;ERRest now also nested insertions, so you could have an update of a Person that does an insert of a new Company specified in the Person.company relationship.  This is arbitrarily nested.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERTaggable&lt;/span&gt;&lt;br /&gt;If you use the default separator in ERTaggable, it now supports parsing tags surrounded by quotes with multiple words.  For instance, you can now tag your objects: tag1 tag2 "multiple word tag3".  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERSelenium&lt;/span&gt;&lt;br /&gt;ERSelenium now includes the necessary requirements for Selenium Remote Control -- see http://selenium-rc.openqa.org/.  It's really cool.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;AjaxSelectionList can now grab focus (focus = true) and has lots of misc fixes.&lt;br /&gt;&lt;br /&gt;AjaxBusyIndicator can now watch a particular updateContainerID and either apply styles to that container, or perform custom onCreate and onComplete functions when a request occurs (note, this is onCreate of the request, and onComplete of the request, to explain the odd naming).  This makes it easier to make per-component busy indicators that don't just trigger on every request.&lt;br /&gt;&lt;br /&gt;AjaxPing now has an onBeforeUpdate binding that you can provide a Javascript function that can deny the update.&lt;br /&gt;&lt;br /&gt;AjaxSubmitButton now has an elementName binding like AjaxUpdateLink.  This allows you to make "clickable divs" (like ERXClickableComponent) that are Ajax submits.&lt;br /&gt;&lt;br /&gt;Some of the Ajax components cached their generated ID values.  These generated values were previously based on the component's element ID.  The problem with this is that when the page structure changes, these components could be left hanging onto an ID that now belongs to another component on the page.  These components now use a new scheme for ID generation that takes advantage of the new ERXResponseRewriter's page userInfo, to generate unique cacheable IDs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc&lt;/span&gt;&lt;br /&gt;ERXFlickrBatchNavigation now supports changing the batch size (showBatchSizes and batchSizes) bindings.&lt;br /&gt;&lt;br /&gt;ERXCommandLineTokenizer provides a parser for parsing "command line"-style parameters, where individual words are single tokens as well as multiple words in double quotes or single quotes.&lt;br /&gt;&lt;br /&gt;ERXFileUtilities.stringFromURL(URL)&lt;br /&gt;&lt;br /&gt;ERXFileUtilities.chmod(String, String) -- only works if you are on an OS that supports chmod&lt;br /&gt;&lt;br /&gt;ERMovies was converted to migrations and should be a little easier to run out-of-the-box.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-4709495011728294484?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/kzjVt0r8FL0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/4709495011728294484/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/05/this-belated-week-in-wonder.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4709495011728294484?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4709495011728294484?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/kzjVt0r8FL0/this-belated-week-in-wonder.html" title="This Belated Week in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/05/this-belated-week-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4FSXc9eyp7ImA9WxZaEEU.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-8995867351136285856</id><published>2008-04-24T17:56:00.000-04:00</published><updated>2008-04-24T21:45:18.963-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-24T21:45:18.963-04:00</app:edited><title>This Week in Wonder</title><content type="html">It's been a pretty busy week (and this is a lame effort to summarize 163 commit messages):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERMovies&lt;/span&gt;&lt;br /&gt;Ray Kiddy updated the movie example to 2008. New features include auto-populating DB and Apache Derby support.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Derby plugin&lt;/span&gt;&lt;br /&gt;Used by BugTracker and ERMovies and now supported by ERPrototypes, it provides preliminary EOF support for &lt;a href="http://db.apache.org/derby/"&gt;Apache Derby&lt;/a&gt;. Most things seem to work, there are some issues with BLOBs, though.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERXDelayedRequestHandler&lt;/span&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;loc:foo and negate:foo prefixes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These are the first implementations for the new prefix registration in the WOOgnl parser. They now also support carret bindings like ^title.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERXLocalizerAssociation&lt;/span&gt;&lt;br /&gt;&lt;code&gt;loc:value = bar &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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&lt;br /&gt;&lt;br /&gt; &lt;code&gt;value = session.localizer.bar&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;or write an accessor method.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERXNegateAssociation&lt;/span&gt;&lt;br /&gt;Ever had an accessor that was just the opposite of what you needed?&lt;br /&gt;&lt;br /&gt; &lt;code&gt;not:disabled = bar &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;helps here.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERXRuntimeUtilities&lt;/span&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;You just call &lt;code&gt;ERXRuntimeUtilities.checkThreadInterrupt()&lt;/code&gt; at regular intervals and the thread that wants to stop calls &lt;code&gt;ERXRuntimeUtilities.addThreadInterrupt(Thread thread, String message)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ERRest&lt;/span&gt;&lt;br /&gt;The REST framework is getting quite a bit of work done on it (with more coming soon).&lt;br /&gt;&lt;br /&gt;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).&lt;br /&gt;&lt;br /&gt;The beginnings of the JSON input/output for ERXRest was committed, though not on by default (still experimental).&lt;br /&gt;&lt;br /&gt;There are several new convenience methods for registering ERXRest.  The simplest is to add:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ERXRestRequestHandler.register(new YourRestAuthenticationDelegate(), true, true);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;to your Application constructor and add Properties entries for registering delegates.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ERXRest.Manufacturer.id=nameOfAttribute&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;, 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.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax Load-on-Demand&lt;/span&gt;&lt;br /&gt;[MS: This is a repost from of the announcement the wonder-disc list] &lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 :)&lt;br /&gt;&lt;br /&gt;So about breaking API changes and behavior changes:&lt;br /&gt;&lt;br /&gt;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).&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc Ajax&lt;/span&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;AjaxObserveField has a new onBeforeSubmit binding that allows you to return false to deny the submit.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc&lt;/span&gt;&lt;br /&gt;ERD2WDirectAction now supports &lt;code&gt;ErrorFoo?__message=bar&lt;/code&gt; calls which is an easy way to put up a error page.&lt;br /&gt;&lt;br /&gt;We moved the work-in-progress stuff from ERXFetchSpecification to ERXGroupingFetchSpecification.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-8995867351136285856?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/BAc-ZJB-kdc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/8995867351136285856/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/04/this-week-in-wonder_24.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/8995867351136285856?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/8995867351136285856?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/BAc-ZJB-kdc/this-week-in-wonder_24.html" title="This Week in Wonder" /><author><name>Anjo Krank</name><uri>http://www.blogger.com/profile/12153571432284820771</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/04/this-week-in-wonder_24.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAHRHg9cSp7ImA9WxZaFUk.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-1531041766751473660</id><published>2008-04-17T08:50:00.000-04:00</published><updated>2008-04-30T03:32:15.669-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-30T03:32:15.669-04:00</app:edited><title>This Week in Wonder</title><content type="html">This Week in Wonder's schedule is all thrown off, but to finally catch us back up:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ERXFetchSpecification&lt;/b&gt;&lt;br /&gt;This is still new and under development, but ERXFetchSpecification extends the concepts of a fetch spec and adds:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;support for caching&lt;/li&gt;&lt;li&gt;type safety via generics&lt;/li&gt;&lt;li&gt;user info for tracking additional information as you pass a fetch spec around&lt;/li&gt;&lt;li&gt;support for grouping results by keypaths&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;One of the primary features here is caching.  In EOF, if you traverse a to-many relationship, the GIDs of the members of that relationship are cached, which ensures that you don't have to do a db roundtrip every time you want to traverse your relationship.  Unfortunately, if you use a fetch spec, there is no such cache provided and you always hit the database.  ERXFetchSpecification allows fetch spec results to be cached to avoid repeatedly hitting the database.  Again, this is still being developed, but Anjo has some very cool ideas for integrating fetch caching with memcached.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;WOOGNL&lt;/b&gt;&lt;br /&gt;The WOOGNL template parser now supports registering custom association prefixes.  You can now set WOOgnl.setAssociationClassForPrefix(associationClass, prefix).  This allows you to implement associations like i18n:value="title", which could load the "title" key from your localized strings.  We haven't yet provided any out-of-the-box association classes yet, but we have several ideas (happily stolen from other frameworks :) ) that we will be implementing.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;JNDI/LDAP&lt;/b&gt;&lt;br /&gt;ERXModelGroup has always allowed replacing connection dictionaries on a model based on Properties values, but it only supported JDBC adaptor models.  JNDI models are now supported with the properties:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[modelName].serverUrl the per-model server URL to set&lt;br /&gt;[modelName].user the per-model username to set&lt;br /&gt;[modelName].password the per-model password to set&lt;br /&gt;[modelName].authenticationModel the per-model authenticationMethod to set&lt;br /&gt;JNDI.global.serverUrl the global JNDI serverUrl to use by default&lt;br /&gt;JNDI.global.username the global JNDI username to use by default&lt;br /&gt;JNDI.global.password the global JNDI password to use by default&lt;br /&gt;JNDI.global.authenticationMethod the global JNDI authenticationMethod to use by default&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Misc&lt;/b&gt;&lt;br /&gt;The new ERXModelDoc component provides a convenient way to display model documentation for a model, entity, attribute, and relationship.&lt;br /&gt;&lt;br /&gt;ERXStyleSheet is more versatile now and supports optionally inlining the stylesheet vs injecting into the head tag.&lt;br /&gt;&lt;br /&gt;You can now provide a custom subclass of the WOOGNL template parser by setting the property "ognl.parserClassName" to your custom subclass.&lt;br /&gt;&lt;br /&gt;Response compression now supports stream-based responses.&lt;br /&gt;&lt;br /&gt;ERXInOrQualifier is no longer on by default.  We had to remove it as the default in 5.4, anyway, because of compatibility problems.  If you want to re-enable it in your application, add &lt;code&gt;EOQualifierSQLGeneration.Support.setSupportForClass(new ERXInOrQualifierSupport(), EOOrQualifier._CLASS);&lt;/code&gt; to your Application constructor.&lt;br /&gt;&lt;br /&gt;ERXQualifierTraversal provides an implementation of the visitor pattern on qualifiers.&lt;br /&gt;&lt;br /&gt;ERXProxyAssociation allows you to wrap an existing WOAssociation and inject a fixed prefix or suffix to the existing value.&lt;br /&gt;&lt;br /&gt;ERXExpiringCache now supports timeouts per-key rather than just a global timeout for all cache entries.&lt;br /&gt;&lt;br /&gt;ERDLinkToEditObject can link to to-one's now.&lt;br /&gt;&lt;br /&gt;ERXEnterpriseObjectChangeListener provides a base class for implementing cache invalidation or other classes that need to be notified of changes to specific entities.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-1531041766751473660?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/hEcwfZsixOc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/1531041766751473660/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/04/this-week-in-wonder_17.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/1531041766751473660?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/1531041766751473660?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/hEcwfZsixOc/this-week-in-wonder_17.html" title="This Week in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/04/this-week-in-wonder_17.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUMQ3k6fyp7ImA9WxZbEEk.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-2585232045025309045</id><published>2008-04-12T18:23:00.000-04:00</published><updated>2008-04-12T19:34:42.717-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-12T19:34:42.717-04:00</app:edited><title>JavaRESTAdaptor</title><content type="html">I know ... There was no "This Week in Wonder" this week.  Mostly because I had "This Week in Real Job".  But here's a new framework in the Wonder family to tide you over till the Next Week in Wonder:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;JavaRESTAdaptor&lt;/b&gt;&lt;br /&gt;Note: My first post called this ERRESTAdaptor, but it's actually JavaRESTAdaptor, because all adaptors have to be named JavaXxxAdaptor.  Whoops.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Overview&lt;/b&gt;&lt;br /&gt;JavaRESTAdaptor is an EOF adaptor implementation on top of a RESTful web service, similar to ActiveResource in Rails.  Currently JavaRESTAdaptor is read-only, but should be sufficient for consuming RESTful services.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Usage&lt;/b&gt;&lt;br /&gt;The usage of JavaRESTAdaptor is best explained in an example.  This example is adapted from an ActiveResource tutorial, but it provides several examples of common techniques. The service we're going to communicate with is a Beast installation.  Beast is a simple Rails forum application.  We'll use http://beast.caboo.se as our example service provider.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Creating the Model&lt;/b&gt;&lt;br /&gt;Note that the instructions here assume that you're using the build of WOLips that builds tonight (to be able to pick "REST" from the adaptor list).&lt;ol&gt;&lt;br /&gt; &lt;li&gt;Create a Wonder project.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Create an EOModel (of any name) and choose "None" from the list of adaptors in the wizard.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;In the default database config (assuming you're using a recent WOLips), select the prototype "EORESTPrototypes" and select the Adaptor "REST".&lt;/li&gt;&lt;br /&gt; &lt;li&gt;In the URL, enter "http://beast.caboo.se" and leave the username and password blank (currently JavaRESTAdaptor does not support HTTP authentication).&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;b&gt;Creating Entites&lt;/b&gt;&lt;br /&gt;Beast provides four entities that we want to interact with: Forum, Topic, Post, User.&lt;ol&gt;&lt;br /&gt; &lt;li&gt;Create an entity named Forum.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;The "table name" of Forum will tell JavaRESTAdaptor the URL extensions and XML tags that can be used to access the entity.  In the case of Forum, the XML tag name comes in two variants -- a singular and a plural form.  For the Forum entity, set the table name to "forum,forums".&lt;br /&gt;&lt;br /&gt;   Table name for JavaRESTAdaptor comes in  several forms:&lt;ul&gt;&lt;li&gt;If you do not set a table name, JavaRESTAdaptor will simply use the entity name as the singular form, and use ERXLocalizer to generate a plural form.&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;If you only set a single value (i.e. "forum"), the adaptor will use that as the singular form and use ERXLocalizer to generate a plural form.&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;If you specify two values (i.e. "forum,forums"), the adaptor will use the first value as the singular form and the second value as the plural form.&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;Additionally, as you will see later, you can specify a set of possibly URL prefixes to use to access the entity.  When you do not specify a URL prefix (as in our Forum example), the adaptor will assume that it can go to /[plural form].xml and /[plural form]/[id].xml to retrieve objects of this entity type.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt; &lt;li&gt;We need to determine the attributes of Forum, so open http://beast.caboo.se/forums.xml in your browser and view the source. ActiveRecord (or more importantly Ruby) can one-up us here, because they automatically  determine the attributes of records based on queries to the service.  We ultimately want to generate Java code, so we need to create an EOModel with attributes.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Forum has the attributes: description, description-html, id, name, position, posts-count, and topics-count. Create attributes in your entity with the names converted to camelCase (description-html becomes descriptionHtml, etc).  For each attribute, select a representative prototype, and set the external name to be the original name from the XML.  For example, descriptionHtml is a "varcharLarge" prototype (we could pick one with a smaller restriction if we want to limit the values) and its external name is "description-html".  postsCount is an "intNumber" and its external name is "posts-count".  Do this for the rest of the attributes of Forum.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;In Beast, forums contain topics, so let's create the Topic entity.  Topics present an interesting issue with modeling, because Beast does not allow you to select topics from the top level, rather you can only select topics through a Forum.  For example, there is no /topics/1.xml there is only /forums/1/topics/1.xml.&lt;br /&gt;&lt;br /&gt;This oddity does cause some problems for EOF, because EOF expects to be able to fetch objects with only a primary key.  JavaRESTAdaptor provides the ability to model fetching these entities, but you should be careful of places where EOF may cause faults for individual objects.  You may find it safer to model relationships to entities of this type in code with fetch specs, or if you're using the Wonder eogen templates, traverse these kind of relationships with forum.topics(null, true), which will force a refetch of the entities.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Request http://beast.caboo.se/forums/1/topics.xml to see an example of what topics look like.  Follow the same procedure as for Forum, creating attributes from the XML.  For dates, use the prototype "dateTime".  For foreign keys, use the attribute "id" and mark them as non-class attributes.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Now to address the URL issue for Topics.  Because there is no /topics.xml, we need to tell JavaRESTAdaptor how to find topic objects.  Edit the Topic entity and set the table name to "/forums/[forumID]/topics,topic,topics". This says that to fetch a topic, you must use the URL "/forums/[forumID]/topics" where forumID is a variable that corresponds to the Topic attribute of the same name.  Any time a fetch is performed on a Topic, a forumID must appear in the qualifier or an exception will be thrown from JavaRESTAdaptor.  When traversing a to-many relationship from a Forum to a Topic, this happens automatically inside of EOF.  However, if you are trying to fetch a particular topic, you must provide its forum in your qualifier to prevent an error.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Now create the Post entity.  Posts are similar to Topics in that you cannot access them from the top level of the service, but they can be accessed in several different ways.  It turns out that you can get posts for a user, for a forum, or for a topic (which requires a forum). JavaRESTAdaptor allows you to model these methods as alternative URLs in the table name by separating the URLs with a pipe.  For instance, the table name for Post is "/users/[userID]/posts|/forums/[forumID]/posts|/forums/[forumID]/topics/[topicID]/posts,post,posts".  I admit this is ugly, and ideally these definitions would be defined on the relationships instead of the entity, but unfortunately at the adaptor level, the EORelationship that was used to fetch the objects is long gone. What ERREST does in this case is that it looks at the qualifier provided and finds the URL that matches the most variables from your qualifier keys and uses that as the fetching URL.  For instance, if your qualifier only has a userID in it, the /users/[userID]/posts URL will be used.  However, if you qualifier has a forumID and a topicID in it, the /forums/[forumID]/topics/[topicID]/posts will be used.  An exception will be thrown if a suitable URL cannot be found given the provided qualifier.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Lastly, create your User entity.  Nothing fancy here, and top-level fetches are allowed, so take a look at http://beast.caboo.se/users.xml to create your attributes, and use the table name "user,users" on this entity.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Relationships&lt;/b&gt;&lt;br /&gt;You have created all of the entities for reading information from Beast.  You can now create the relationships between these entities.  For entities that can be fetched from the top level, or when modeling relationships that will provide enough context for the fetch, relationships can be modeled just like a normal eomodel.&lt;br /&gt;&lt;br /&gt;For instance, from post.user() is a completely normal to-one relationship because User can be fetched from the top level, and post will provide the "id" necessary to execute the fetch.  Similarly, forum.topics() is a normal to-many relationship, because while Topic does not have a topic level fetch URL, traversing the relationship from Forum will provide the "forumID" necessary to complete the fetch.&lt;br /&gt;&lt;br /&gt;The "problem child" relationships are, for instance, topic.posts().  Traversing the posts relationship on Topic will only provide a topicID.  Unfortunately Posts requires a topicID AND a forumID.  It turns out that this can be modeled by putting both topicID and forumID in the joins of the to-many relationship definition.  The downside of this is that it will not be symmetric with the other side of the relationship, and will not be updated automatically when write ability is added to JavaRESTAdaptor.  The other problem is that, while this technique works on to-many relationships, it does not work on to-one relationships.  EOF does not allow a to-one relationship to be defined with a join on anything expect a primary key attribute.&lt;br /&gt;&lt;br /&gt;In this  situation, you will need to construct the relationship using a fetch spec, and not using normal relationship definitions in the model.  Your fetch spec will work just like a normal fetch spec, but you must provide all variables necessary to complete a fetch.  As an example, if you want to fetch a particular topic, you must fetch it like:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Topic singleTopic = Topic.fetchRequiredTopic(editingContext, Topic.FORUM.eq(aForum).and(ERXQ.equals("id", 633)));&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;aForum.topics(ERXQ.equals("id", 633), true)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Note that JavaRESTAdaptor allows fetching on non-class attributes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Fetching Notes&lt;/b&gt;&lt;br /&gt;When fetching against the remote service, only topic level EOKeyValueQualifiers, EOAndQualifiers, and EOOrQualifiers with a single entry will be processed for constructing the remote URL.  Complex qualifiers can be constructed, but they will be evaluated in-memory against the most restrictive URL that could be constructed given your qualifier attributes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Examples&lt;/b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;EOEditingContext editingContext = ERXEC.newEditingContext();&lt;br /&gt;&lt;br /&gt;NSArray&lt;Forum&gt; forums = Forum.fetchAllForums(editingContext);&lt;br /&gt;System.out.println("Application.Application: Fetching all forums");&lt;br /&gt;for (Forum forum : forums) {&lt;br /&gt;  System.out.println("Application.Application:   " + forum.name() + ", " + forum.postsCount() + ", " + forum.topicsCount());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;System.out.println("Application.Application: Fetching forum w/ PK");&lt;br /&gt;Forum singleForum = (Forum) EOUtilities.objectWithPrimaryKeyValue(editingContext, Forum.ENTITY_NAME, "3");&lt;br /&gt;System.out.println("Application.Application:   " + singleForum.name());&lt;br /&gt;&lt;br /&gt;System.out.println("Application.Application: Fetching topics for " + singleForum.name());&lt;br /&gt;NSArray&lt;Topic&gt; topics = singleForum.topics();&lt;br /&gt;for (Topic topic : topics) {&lt;br /&gt;  System.out.println("Application.Application:   " + topic.title() + " created " + topic.createdAt());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;System.out.println("Application.Application: Fetching posts for forum");&lt;br /&gt;NSArray&lt;Post&gt; forumPosts = singleForum.posts();&lt;br /&gt;for (Post post : forumPosts) {&lt;br /&gt;  System.out.println("Application.Application:   " + post.createdAt());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;System.out.println("Application.Application: Refetching single topic w/ PK");&lt;br /&gt;Topic singleTopic = Topic.fetchRequiredTopic(editingContext, Topic.FORUM.eq(singleForum).and(ERXQ.equals("id", 633)));&lt;br /&gt;System.out.println("Application.Application:   " + singleTopic.title());&lt;br /&gt;&lt;br /&gt;System.out.println("Application.Application: Fetching topic user");&lt;br /&gt;User user = singleTopic.user();&lt;br /&gt;System.out.println("Application.Application:   " + user.displayName());&lt;br /&gt;&lt;br /&gt;System.out.println("Application.Application: Fetching posts for topic (composite pk, which is kind of interesting)");&lt;br /&gt;NSArray&lt;Post&gt; topicPosts = singleTopic.posts();&lt;br /&gt;for (Post post : topicPosts) {&lt;br /&gt;  System.out.println("Application.Application:   " + post.createdAt());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Post randomPost = topicPosts.lastObject();&lt;br /&gt;System.out.println("Application.Application: Fetching the topic for a post (this will break if topic is not already fetched)");&lt;br /&gt;System.out.println("Application.Application:   " + randomPost.topic().title());&lt;br /&gt;&lt;br /&gt;System.out.println("Application.Application: Fetch author of post");&lt;br /&gt;User postedByUser = randomPost.user();&lt;br /&gt;System.out.println("Application.Application:   " + postedByUser.displayName());&lt;br /&gt;&lt;br /&gt;System.out.println("Application.Application: Fetching posts by author");&lt;br /&gt;NSArray&lt;Post&gt; userPosts = postedByUser.posts();&lt;br /&gt;for (Post post : userPosts) {&lt;br /&gt;  System.out.println("Application.Application:   " + post.createdAt());&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Check out JavaRESTAdaptorExample project to see the model described here fully completed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-2585232045025309045?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/lIljtU7wgg4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/2585232045025309045/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/04/errestadaptor.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/2585232045025309045?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/2585232045025309045?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/lIljtU7wgg4/errestadaptor.html" title="JavaRESTAdaptor" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>5</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/04/errestadaptor.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYAQnk4fSp7ImA9WxZUEUQ.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-2736797813296358800</id><published>2008-04-02T22:10:00.000-04:00</published><updated>2008-04-02T22:35:43.735-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-02T22:35:43.735-04:00</app:edited><title>This Week In Wonder</title><content type="html">The big one for this week is much better 5.4.x support.  We've fixed quite a few outstanding issues and we should be in a pretty good place when the next 5.4.x release comes out (which is looking good).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wonder/5.4 Changes&lt;/b&gt;&lt;br /&gt;&lt;i&gt;ERXWOForm&lt;/i&gt;&lt;br /&gt;ERXWOForm works properly with the new 5.4 context.isSecure setting (defaulting to secure if context.isSecure())&lt;br /&gt;&lt;br /&gt;&lt;i&gt;ERXWOConditional/ERXElse&lt;/i&gt;&lt;br /&gt;ERXWOConditional/ERXElse simply cannot play nicely with 5.4 wo:if/wo:else.  In the 5.4 build of Wonder, a notable change is that you need to pick your conditional horse.  In 5.4, WOConditional will no longer be automatically replaced by ERXWOConditional.  WOOgnl's wo:if and wo:else will still resolve to the ERX variant, but if you use WOConditional directly and you want the Wonder behavior, you will need to search for all ":\s*WOConditional" and change them to ": ERXWOConditional".  We looked at this quite a bit, but the semantic of the "else" implementation in 5.4 is very different than Wonder's, and continuing to replace WOConditional in the way that we do would break any 3rd party 5.4 components (like Apple's) that are written to expect if/else to work like 5.4's.&lt;br /&gt;&lt;br /&gt;[edit: Oh -- I forgot to mention.  If you DO NOT intend to use 5.4's if/else and you just want to switch to 5.4 without having to change your components, you can set er.extensions.WOConditional.patch=true and it will override the default disabled patching of WOConditional to be ERXWOConditionl.  At the moment this should be OK, because none of the Apple components use their if/else, but in the longer term, you should switch over to ERXWOConditional if you intend to use ERXElse]&lt;br /&gt;&lt;br /&gt;&lt;i&gt;ERMemoryAdaptor&lt;/i&gt;&lt;br /&gt;This .... actually builds now in 5.4.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;ERXWOContext&lt;/i&gt;&lt;br /&gt;Through a small bit of trickery, ERXWOContext URL rewriting fully works with 5.4's new context API's.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Foundation&lt;/i&gt;&lt;br /&gt;The 5.3 Wonder NS* collections classes better match the 5.4 versions so there should be fewer compatibility issues (which was an issue if you were running 5.4 code with the ERExtensions project checked out).&lt;br /&gt;&lt;br /&gt;&lt;i&gt;FrontBasePlugIn and PostgresqlPlugIn&lt;/i&gt;&lt;br /&gt;Both of these plugins have been updated/slightly mangled to properly generate SQL under both 5.3 and 5.4 (as long as you aren't calling the new 5.4 schema sync API's).  Pierre has merged nearly all (except the latest feature where you can generate SQL without a running database) of the Wonder FrontBasePlugIn features into 5.4, and it fully implements both the 5.3 and 5.4 schema sync API's, so Apple's should be the preferred one under 5.4.  Wonder still maintains the primary PG plugin, though, so you will be limited to 5.3 schema sync for now.  If you're doing anything with schema sync/sql gen, you need to be very careful of what API's you are using -- it's a bit of a minefield in 5.4 when you're using anything except the built-in plugins.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Source&lt;/i&gt;&lt;br /&gt;Almost all of Wonder runs under both 5.3 and 5.4 without mucking with your build path.  However, because of some refactorings in WOOgnl, if you are checking out the Wonder source in Eclipse, you will have to remove the Sources_WO53 from your WOOgnl build path and add Sources_WO54 to your build path if you intend to use 5.4.  There was unfortunately no obvious way around one.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Other Misc Things&lt;/b&gt;&lt;br /&gt;Ajax/ERXFlickrBatchNavigation now support pagination of plain java arrays without using a display group, which should make it easier to paginate non-WOish collections.&lt;br /&gt;&lt;br /&gt;ERXKey supports an easier API for filtering arrays.  For instance:&lt;br /&gt;&lt;br /&gt;NSArray&lt;Company&gt; filteredCompanies = Company.NAME.is("Mike").filter(arrayOfCompanies);&lt;br /&gt;&lt;br /&gt;WOLips.framework and Click2Open now work under FireFox and IE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-2736797813296358800?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/QtoVwlgE4gU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/2736797813296358800/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/04/this-week-in-wonder.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/2736797813296358800?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/2736797813296358800?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/QtoVwlgE4gU/this-week-in-wonder.html" title="This Week In Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/04/this-week-in-wonder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMAQX87fyp7ImA9WxZVFUk.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-4668763387797402518</id><published>2008-03-26T11:44:00.000-04:00</published><updated>2008-03-26T11:47:20.107-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-26T11:47:20.107-04:00</app:edited><title>This week in Wonder</title><content type="html">&lt;span style="font-weight:bold;"&gt;AjaxModalContainer updated&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The AjaxModalContainer has been updated to ibox 2.17. It now has an example with the various options it supports, like images, inline content, external URLs etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-4668763387797402518?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/iHBYuDNBFvY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/4668763387797402518/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/03/this-week-in-wonder_26.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4668763387797402518?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4668763387797402518?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/iHBYuDNBFvY/this-week-in-wonder_26.html" title="This week in Wonder" /><author><name>Anjo Krank</name><uri>http://www.blogger.com/profile/12153571432284820771</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/03/this-week-in-wonder_26.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UDQ34_eCp7ImA9WxZVEE8.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-7805026212720670139</id><published>2008-03-19T20:16:00.000-04:00</published><updated>2008-03-20T09:54:32.040-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-20T09:54:32.040-04:00</app:edited><title>This Week In Wonder</title><content type="html">&lt;span style="font-weight:bold;"&gt;Misc Stuff&lt;/span&gt;&lt;br /&gt;AjaxTabbedPanel tracks selected tabs and allows you track the selection.  Check out AjaxTabbedPanelDemo for an example.&lt;br /&gt;&lt;br /&gt;ERXStyleSheet generates a &amp;lt;link&amp;gt; tag. For non-XHTML, browsers expect the link tag to not have a closing tag.  You can now set "er.extensions.ERXStyleSheet.xhtml=false" to make your link tags not generate a closing tag.&lt;br /&gt;&lt;br /&gt;ERXWOContext now has a bunch of static directActionUrl(..) generation methods that allow you to override various combinations of host name, port, path, directaction name, http/https, and query string params.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JSON&lt;/span&gt;&lt;br /&gt;The big one for this week is the enhanced JSON features (with a lot more surprises coming).  We've had page-based JSON proxy support almost since the beginning, but it has been enhanced quite a bit along with the addition of a JSON Request Handler for JSON web services.  We've upgraded our implementation from the old metaparadigm.com JSON library to the new &lt;a href="http://www.jabsorb.org/"&gt;jabsorb.org&lt;/a&gt; library (which metaparadigm turned into).  We also spent some time to add some new JSON EO features.  One of the problems we had previously was the complexity of the demo app for JSON.  There are now much easier examples that show just how simple it is to pass data around.  You can hand an NSArray of EO's to your browser client and the browser can make changes and hand them back -- more to come on this front.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Stateful Page Clients&lt;/span&gt;&lt;br /&gt;Do you need access to stateful objects from your component in the browser?  Just bind:&lt;br /&gt;&lt;pre class="wod"&gt;&lt;br /&gt;AjaxProxy : AjaxProxy {&lt;br /&gt; name = "json";&lt;br /&gt; proxyName = "example";&lt;br /&gt; proxy = proxy;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;make a "proxy" method that returns an object that you want to be able to message (if you leave the proxy binding off, it will bind to your component directly):&lt;br /&gt;&lt;pre class="java"&gt;&lt;br /&gt;public SomeProxyObject proxy() {&lt;br /&gt; return _proxy;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class SomeProxyObject {&lt;br /&gt;public NSArray&lt;person&gt; people() { ... } // these can be EO's!&lt;br /&gt;public void doSomethingWithAPerson(Person person) { ... }&lt;br /&gt;}&lt;br /&gt;&lt;/person&gt;&lt;/pre&gt;&lt;br /&gt;and then in javascript:&lt;br /&gt;&lt;pre class="js"&gt;&lt;br /&gt;var people = json.example.people();&lt;br /&gt;people.nsarray.each(function(person, index) { alert(person.firstName); }&lt;br /&gt;json.example.doSomethingWithAPerson(people[0]);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's pretty cool how easy it is.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JSON Web Services&lt;/span&gt;&lt;br /&gt;Or you can use JSON for web services instead of SOAP/WOWebServices:&lt;br /&gt;&lt;br /&gt;In your Application:&lt;br /&gt;&lt;pre class="java"&gt;&lt;br /&gt;JSONRequestHandler requestHandler = JSONRequestHandler.register();&lt;br /&gt;requestHandler.registerService("exampleService", new ExampleService());&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Your service class is similar to a registered WOWebService class:&lt;br /&gt;&lt;pre class="java"&gt;&lt;br /&gt;public class ExampleService {&lt;br /&gt;   public void printThisString(String string) { .. }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;JSON services also support "local args", which allow the server to fill in parameters to your method for you based on the request.  For instance, if your method is stateful and you need a session, you can just add a WOSession parameter to your method:&lt;br /&gt;&lt;pre class="java"&gt;&lt;br /&gt;public class ExampleService {&lt;br /&gt; public void printThisStringStateful(WOSession session, String string) { .. }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And you will be given a session, and the session will be maintained with cookies.  The external signature of the method does not change.  This works for WOSession, WORequest, WOResponse, and WOContext.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JSON Browser Client&lt;/span&gt;&lt;br /&gt;If you want to call your JSON service from a component:&lt;br /&gt;&lt;pre class="js"&gt;&lt;br /&gt;&amp;lt;webobject name = "AjaxJSONClient"/&amp;gt;.exampleService.printThisString('hi');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="wod"&gt;&lt;br /&gt;AjaxJSONClient : AjaxJSONClient {&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JSON Java Client&lt;/span&gt;&lt;br /&gt;If you need JSON in a Java client app:&lt;br /&gt;&lt;pre class="java"&gt;&lt;br /&gt;Client client = JavaJSONClient.create("http://yourhost/cgi-bin/WebObjects/YourApp.woa/-yourPort/json", true);&lt;br /&gt;IExampleService exampleService = (IExample) client.openProxy("exampleService", IExampleService.class);&lt;br /&gt;exampleService.printhisString("hi");&lt;br /&gt;&lt;br /&gt;public interface IExampleService {&lt;br /&gt;   public void printThisString(String str);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;(the "true" means you want to use HttpClient as the backing impl, which requires you have that installed in your classpath).  Currently there is no stubs generator, so you have to write the stub classes yourself.  For most classes it's pretty straightforward (just write the accessor methods).  For EO's, it's the same, but you should extend JSONEnterpriseObject on the client.  JSONEnterpriseObject just exposes a set/getGlobalID method for tracking purposes.  Note that EO's in a Java JSON client app do not track changes -- they only support pass-by-reference right now.  That may change at some point.&lt;br /&gt;&lt;br /&gt;Check out JSONExample in the AjaxExample app for a bunch of examples that show various ways to use the feature.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-7805026212720670139?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/LpfhttoPsnc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/7805026212720670139/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/03/this-week-in-wonder_19.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/7805026212720670139?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/7805026212720670139?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/LpfhttoPsnc/this-week-in-wonder_19.html" title="This Week In Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/03/this-week-in-wonder_19.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8NQ3wzfyp7ImA9WxZWE0s.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-5934792861687188039</id><published>2008-03-12T19:10:00.000-04:00</published><updated>2008-03-12T19:34:52.287-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-12T19:34:52.287-04:00</app:edited><title>This Week in Wonder</title><content type="html">&lt;span style="font-weight:bold;"&gt;Automatic Inverse Relationship Updating&lt;/span&gt;&lt;br /&gt;This feature was partially implemented a while back, but it didn't work in all cases.  This now should work all the time (Chuck! It has test cases!).  Essentially what it means is that you no longer have to think about addObjectToBothSidesOfBlah or removeObjectFromBothSidesBlah, you can just use the normal EOF methods and it will automatically call the necessary methods to update your relationships.&lt;br /&gt;&lt;br /&gt;The EOGenerator templates that ship with WOLips (and that were inherited from some long-since-paste original version) have always had methods that made this easier -- the person.setCompanyRelationship(company) and company.addToEmployeesRelationship(Person person) methods, and these are nice in code, but you are vulnerable in certain cases (like binding in components) that don't know about those methods and can leave you with only one side being updated properly.&lt;br /&gt;&lt;br /&gt;There are new Wonder templates in WOLips that provide overrides for the core setXxx method variants, and they check to see if inverse updating is enabled.  If it is, then the new way will be used, if not, the old way will be.  So in the above example, when auto-updating of inverse relationships is enabled, you can can person.setCompany(company) and company.addToEmployees(person), and it will Do The Right Thing™.&lt;br /&gt;&lt;br /&gt;To enable it, in your Properties file, just set:&lt;br /&gt;&lt;br /&gt;er.extensions.ERXEnterpriseObject.updateInverseRelationships=true&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Misc API&lt;/span&gt;&lt;br /&gt;ERXJavaScript now has the same binding naming conventions as ERXStyleSheet (and the rest of WO) -- framework = "xxx" filename = "yyy", though the old bindings are still maintained.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Utilities&lt;/span&gt;&lt;br /&gt;ERXUtilities.deepClone (for anything -- it will call the corresponding object, array, or dictionary methods), ERXArrayUtilities.deepClone (for arrays), and ERXDictionaryUtilities.deepClone (for dictionaries) have been added.  If you ever run into a situation where cloning a dictionary is not enough, and you need to clone arrays and dictionaries INSIDE that dictionary, these are the methods for you.  deepClone will attempt to recursively clone all of the objects in the graph.  You can optionally have it clone just the collections or the leaf nodes as well.  Leaf nodes will only clone if they implement Cloneable and provide a clone method -- Currently this will not properly clone EO's, for instance.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Database PlugIns&lt;/span&gt;&lt;br /&gt;There's been a long-standing totally annoying (what I consider a) bug in EOF that you have to open a database connection to be able to retrieve jdbc2Info, which is required to do things like SQL generation.  If you've ever noticed when you made a new model in EOModeler, or when you try to generate SQL in Entity Modeler, it would yell at you if it couldn't connect to your DB, that's why.  jdbc2Info contains things like database type information, which is almost always static with your database version.  &lt;br /&gt;&lt;br /&gt;Thanks to Andrew Lindesay, the plugins in Wonder (Postgresql and FrontBase right now) both now provide overrides for loading jdbc2Info from a static resource in the plugin jar, which means you can fully create a model and generate SQL without needing a database connection.&lt;br /&gt;&lt;br /&gt;For postgresql, make your connection string: jdbc:postgresql://yourhost/yourdb?useBundledJdbcInfo=true&lt;br /&gt;&lt;br /&gt;For FrontBase, make your connection string: jdbc:FrontBase://yourhost/yourdb/useBundledJdbcInfo=true&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Click-To-Open&lt;/span&gt;&lt;br /&gt;Chuck documented Click-To-Open support &lt;a href = "http://wiki.objectstyle.org/confluence/display/WOL/Click+to+Open"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt;&lt;br /&gt;Ajax framework has been upgraded to Prototype 1.6 and Scriptaculous 1.8.  Check your apps accordingly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-5934792861687188039?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/_nB6ctGa8xU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/5934792861687188039/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/03/this-week-in-wonder_12.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/5934792861687188039?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/5934792861687188039?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/_nB6ctGa8xU/this-week-in-wonder_12.html" title="This Week in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/03/this-week-in-wonder_12.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQMSXs8eip7ImA9WxZXF08.&quot;"><id>tag:blogger.com,1999:blog-3800915079618757848.post-4401430788660098500</id><published>2008-03-05T09:02:00.000-05:00</published><updated>2008-03-05T09:46:28.572-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-05T09:46:28.572-05:00</app:edited><title>This Week in Wonder</title><content type="html">Every two weeks might make more sense, but as soon as I say that, they'll be a flurry of commits to Wonder and it will be a huge post :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Migrations&lt;/span&gt;&lt;br /&gt;Migrations were made more compatible for people not using ERPrototypes. One of the tricky parts of migrations is converting the API request into a database type (for instance, getting newStringColumn to turn into a VARCHAR in your db).  EOF doesn't do a very good job at guessing these values, and in some cases it's impossible to guess.  When you use ERPrototypes, we can secretly cheat and lookup some known prototype values.  If you don't, though, we have to guess effectively.  The guessing code was made better, as well as an explicit override for an unguessable type in Postgresql.  So migrations should work properly for PG and FB (at least) even if you don't use ERPrototypes now.&lt;br /&gt;&lt;br /&gt;Why aren't you using ERPrototypes again?  When you use ERPrototypes, Entity Modeler will work more efficiently as well.  For instance, when you create a new entity, it will automatically give you an "id" column that is of the "id" prototype.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Property Operators (Properators?)&lt;/span&gt;&lt;br /&gt;There are certain cases where you want to be able to have conditional Properties, or properties that get processed in some special way at load time.  Wonder now offers support for "property operators".  Similar to NSArray operators, you can register operators that will allow you to convert, extend, modify, and add properties during the loading process.&lt;br /&gt;&lt;br /&gt;As an example, you can register and use the "Encrypted" operator in your Application's static block (these have to load very early):&lt;br /&gt;&lt;br /&gt;static {&lt;br /&gt;    ERXProperties.setOperatorForKey(new ERXProperties.EncryptedOperator(), ERXProperties.EncryptedOperator.Key);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;and you can then specify properties like:&lt;br /&gt;&lt;br /&gt;com.mdimension.somesecretvalue.@encrypted=akxb)*@HASBC*#@$&amp;%&amp;@(NSJKX&amp;XZ#&lt;br /&gt;&lt;br /&gt;which will use Wonder's default crypter to decrypt the value when it loads.&lt;br /&gt;&lt;br /&gt;Or, if you happen to have, say, a really really big WO deployment, you may want to override properties based on instance range, so you can register the InRange operator named "forInstance":&lt;br /&gt;&lt;br /&gt;static {&lt;br /&gt;    ERXProperties.setOperatorForKey(new ERXProperties.InRangeOperator(ERXProperties.intValueForKey("yourInstanceNumber")), ERXProperties.InRangeOperator.ForInstanceKey);&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;and make a property:&lt;br /&gt;com.mdimension.somethingNotReadyForFullDeployment.@forInstance.100-500,1000-1500=sometestvalue&lt;br /&gt;&lt;br /&gt;Note that instance number is a per-request concept, generally, so it's up to you to specify what "instance number" means to your app (so you would have to define and pass in instance number in Java Monitor).  This is a pretty specialized feature, but if you have the problem, this should help.&lt;br /&gt;&lt;br /&gt;You can write and register your own operators, though, so if you ever have to perform some processing on keys and values, you know where to look.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3800915079618757848-4401430788660098500?l=projectwonder.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/projectwonder/~4/xWIDFtqP3hM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://projectwonder.blogspot.com/feeds/4401430788660098500/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://projectwonder.blogspot.com/2008/03/this-week-in-wonder.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4401430788660098500?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3800915079618757848/posts/default/4401430788660098500?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/projectwonder/~3/xWIDFtqP3hM/this-week-in-wonder.html" title="This Week in Wonder" /><author><name>Mike Schrag</name><uri>http://www.blogger.com/profile/07185879942719846837</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://projectwonder.blogspot.com/2008/03/this-week-in-wonder.html</feedburner:origLink></entry></feed>

