Saturday, May 3, 2008

This Belated Week in Wonder

EOF
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.

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:


ERXJDBCUtilities.processResultSet(channel, "select id from SomeTable", new ERXJDBCUtilities.IResultSetDelegate() {
  public void processRow(EOAdaptorChannel rsChannel, ResultSet rs) throws Exception {
    int id = rs.getInt("id");
    ERXJDBCUtilities.executeUpdate(rsChannel, "update SomeTable set uuid = '" + something + "' where id = " + id);
  }
});

There is now a longInt prototype added to ERPrototypes.

Qualifiers
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).

All qualifiers in Wonder now are chainable qualifiers.

ERXQ now provides the new shortcut methods .matches(..) (for regex qualification), .has(..) and .hasAtLeast(..) (for toMany qualifiers).

Properties
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 .

ERRest
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:

EOEditingContext editingContext = ERXEC.newEditingContext();

ERXDefaultRestDelegate restDelegate = new ERXDefaultRestDelegate();
restDelegate.addDelegateForEntityNamed(new ERXUnsafeRestEntityDelegate(true), YourEntity1.ENTITY_NAME);
restDelegate.addDelegateForEntityNamed(new ERXUnsafeRestEntityDelegate(true), YourEntity2.ENTITY_NAME);
...
ERXRestContext restContext = new ERXRestContext(context(), editingContext, restDelegate);

String restPath = "Person";
URL remoteUrl = new URL("http://remotesite/rest/" + restPath + ".xml");
String contentStr = ERXFileUtilities.stringFromURL(remoteUrl);
ERXRestRequest restRequest = new ERXXmlRestRequestParser().parseRestRequest(restContext, contentStr, restPath);
ERXRestKey restResponse = restDelegate.process(restRequest, restContext);

editingContext.saveChanges();

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.

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.

ERTaggable
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".

ERSelenium
ERSelenium now includes the necessary requirements for Selenium Remote Control -- see http://selenium-rc.openqa.org/. It's really cool.

Ajax
AjaxSelectionList can now grab focus (focus = true) and has lots of misc fixes.

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.

AjaxPing now has an onBeforeUpdate binding that you can provide a Javascript function that can deny the update.

AjaxSubmitButton now has an elementName binding like AjaxUpdateLink. This allows you to make "clickable divs" (like ERXClickableComponent) that are Ajax submits.

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.

Misc
ERXFlickrBatchNavigation now supports changing the batch size (showBatchSizes and batchSizes) bindings.

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.

ERXFileUtilities.stringFromURL(URL)

ERXFileUtilities.chmod(String, String) -- only works if you are on an OS that supports chmod

ERMovies was converted to migrations and should be a little easier to run out-of-the-box.

No comments:

Post a Comment