Sunday, April 19, 2009

Need More Rest

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

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

in your Application constructor:


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

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

then you can make a controller class:

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

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

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

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

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

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

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

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

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


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


As an example of actually hitting the API, btw:

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

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

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

is the same thing in JSON, and

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

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

Saturday, March 21, 2009

The "I Have A Day Job" Edition

ERRest
support for plist and json responses

support for simple qualifiers and sort orderings in query params

lots of API's for programmatically generating responses

ERDirectToRest
initial pass at a D2W version of the ERRest framework

ERPlot
Updated to latest JFreeChart

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

Support for custom prototype overrides in ERXModelGroup.

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

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

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

Ajax
Ajax scripts are compressed during the build process.

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

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

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

Maven
BUILD.txt updated with latest maven build instructions

Misc
Utilities/WOInstall - source of WOInstaller.jar

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

WOJavaRebel
Updated for JavaRebel 2.0

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

JavaMonitor
refactored the confirm pages to use just one page

added 'stop all' for selected instances

added 'delete all' for selected instances

more directactions controls

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

added bounce action

Components
ERXLanguageMenu - generic picker for selecting your current language

... and a gazillion bug fixes

Sunday, December 14, 2008

This Week in Wonder

Ajax
AjaxModalDialogOpener lets you separate the opening of a modal dialog from the dialog itself.

Updated to Scriptaculous 1.8.2

AjaxSortOrder is an ajax version of ERXSortOrder.

Components
Support for quicktime attachments in ERAttachment.

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.

EOF
Wonder Migrations can now be used without using ERXEC.

New, better, implementation of SQL parsing (for executing SQL scripts).

Migrations now support SQLServer (well, more than they did).

New Frameworks
WOJavaRebel framework provides support for easily running WO apps with JavaRebel for modifying classes on-the-fly without restarting.

Utilities
New warnings when you are possibly misusing ERXThreadStorage.

ERXEOControlUtilities. validateUniquenessOf provides a utility method for validating unique EO attribute values.

Application
You can now set a low memory threshold separate from a memory starvation threshold, and both now fire notifications that you can respond to.

Support for making ERXResourceManager generate complete resource URLs by setting context. _setGenerateCompleteResourceURLs.

Simple resource rewriting -- Set er.extensions.ERXResponseRewriter.resource.frameworkName.filePath = newFrameworkName.newFilePath

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.

Support for SSL with DirectConnect. Here's the pertinent docs from Properties:
#########################################################################
# SSL DirectConnect
#########################################################################
## You should probably not enable any of these settings in a normal Apache webserver deployment,
## in particular the ssl port property, as this is used by ERX to generate https URLs, which must
## match your Apache config.
##
## To enable SSL support with DirectConnect, you must do the following:
##
## * In your Resources folder, run "keytool -genkey -alias WebObjects -keyalg RSA -keystore adaptorssl.key". Select a
## password for your keystore (i.e. "changeit"), and set the "your first name and last name" field to match the hostname
## that you will be running your directconnect app off of.
## * In your Resources folder, create an executable script (it MUST BE EXECUTABLE) named "adaptorsslpassphrase" with the
## contents:
## echo changeit
## where you should replace "changeit" for whatever password you selected in the previous step.
## * Set the following property to true
#er.extensions.ERXApplication.ssl.enabled=true

## (optional) To specify an SSL host name other than what is returned from a call to
## application.host(), you can override it below
#er.extensions.ERXApplication.ssl.host=localhost

## (optional) To select an SSL port other than 443, uncomment the following. If you are already running Apache with SSL,
## you probably want to set this. If the port number is 0, the SSL port will be automatically assigned (using the same
## mechanism that WO uses to set the regular port)
#er.extensions.ERXApplication.ssl.port=0

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

Friday, November 21, 2008

These 49 Days in Wonder

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

We cleared a lot of the backlog of patches in Jira ... Sorry it took us so long.

Ajax
Ajax framework was updated to Prototype 1.6.0.3

AjaxSocialNetwork and AjaxSocialNetworkLink provides support for submitting URLs to a heap of social linking sites using their recommended icons

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

ERXAccessibleSubmitButton provides support for defining hot keys for submit buttons.

ERXJSToManyRelationshipEditor provides a nice javascript-based to-many relationship editor

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

ERXRedirect supports redirecting to a stateful component (in addition to several other variants).

EOF
New "javaEnum" prototype ... Select it and just set the valueClassName to point to your java Enum class.

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

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.

ERExtensions
Added ERXSession support for requiring secure session cookies to prevent session hijacking.

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)

ERXYahooContentAnalysisService connects to Yahoo's term extraction service (for use with auto-tagging)

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

WOOgnl no longer requires a different source path for 5.3 and 5.4, though it does require a different binary framework.

Lots of fixes to SproutCore framework to bring it more in line with the latest SproutCore releases.

Friday, October 3, 2008

This Belated Week in Wonder

Yeah. It's been a few weeks. I know .... Better late than never:

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

By popular demand, AjaxTabbedPanel can now hide tabs.

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.

There's a new example of using AjaxModalContainer in AjaxExample2.

Chuck fixed tons of weird little border cases.

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.

ERExtensions
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 the javadoc 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.

ERXApplication can now load Properties from inside of jar frameworks.

multipleSubmit=true is now defaulted on for all WOForms. Rest in peace stupid binding.

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

ERXDisplayGroup now uses generics.

ERXKey now uses generics in all of the .is(..) etc methods.

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.

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.

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.

ERPrototypes
New IP Address prototype (along with new migration methods to support it).

New byte24 prototype for generating guid PKs.

Maven
Both the 5.3 and 5.4 version of Wonder can be now be built with Maven. Talk to Henrique for more info :)

ERAttachment
You can now register a custom delegate 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.

Friday, August 22, 2008

This Week in Wonder

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

ibox.js in AjaxModalContainer was updated to 2.17b

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.

AjaxModalContainer has a new locked flag that disallows closing and an open flag that forces it open (rather than waiting for a click).

AjaxModalContainer works with HTTPS URLs now.

New AjaxUtils.arrayValueForBinding utility method, which supports loading array bindings that are defined as references to NSArray as well as inline JSON-syntax Strings.

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

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

ERXJDBCConnectionBroker has a new fix for a resource contention problem with leaving connections in an incorrect state.

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

Components
Ravi Mendis has committed fixes for XHTML compliance in several components.

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

ERXExtensions.initApp and ERXExtensions.initEOF should be a little easier to use now. In your JUnit TestSuites, you can just add a static method:


static {
ERXExtensions.initApp(Application.class, new String[0]);
}


and you will be running your test case in a full Wonder-ful Application environment.

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

Google Chart
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 more info here.

Friday, August 8, 2008

These 9 Weeks in Wonder

 Yeah, I know, long time no write ... Occasionally Real Work (TM) gets in the way.

Migrations
newLocalizedStringColumn supports creating string columns that work with Wonder's localized attributes ("name_en," "name_de," etc).

Migration support for dropping composite pks (though the FrontBase plugin doesn't actually support this :( ).

BigInteger column support.

newFlagBooleanColumn which generates a Types.BOOLEAN column instead of a varchar(5) or int boolean column.

ERIndexing
Updated to Lucene 2.3.2.

ERIndexingExample is a new example app that shows how to use ERIndexing.

ERCaching
More work on memcached integration, though I think (correct me if I'm wrong, Anjo?) it's not quite ready for primetime yet.

ERSelenium
StandaloneRunner supports running Selenium tests from the commandline.

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

Check out the SproutCoreExample app to see it in action.

Wonder 2.0
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.

JSON
Lots of work on JSON support in Ajax framework.

You can now optionally include attributes and relationships in your JSON results via the client class property setting in your model.

You can specify writable vs read-only attributes.

Marshalling/unmarshalling of EOTemporaryGlobalIDs is supported, so you can pass around uncommitted EO's to/from the server.

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

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.

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.

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

ERExtensions
ERXRemoteNotificationCenter provides support for posting arbitrary notifications across multiple servers. Provides a simple implementation as well as a JGroups implementation.

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.

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.

ERXFlashMovie is just a handy wrapper around embedding an SWF in a page.

ERXEOGlobalIDUtilities does a lot more work to make sure that it doesn't refetch objects that were already faulted.

ERXQ.containsObject. If you're a fan of the "contains" qualifier selector, you'll be a fan of this method.

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.

ERXDatabaseContextMulticastingDelegate now supports both 5.3 and 5.4.

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.

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.

ERXMutableURL is a little smarter about not generating :80's for http and :443's for https.

ERXEOAccessUtilities.createRelationship and createFlattenedRelationship provide easier methods for programatically mucking with your EOModels

ERXEOControlUtilities.distinctValuesForKeyPath will give you an array of the distinct values of a particular keypath on an entity.

ERXModernNavigationMenu/Item provides an upgraded replacement of ERXNavigationMenu/item that are CSS and semantic markup instead of the older table-based layout.

ERXArrayChooser now supports arbitrary qualifiers and fetching of shared objects.

ERXModuloQualifier can generate SQL queries that use the "mod" keyword.

ERXFetchSpecificationBatchIterator now supports prefetching and raw rows.

ERXGenericRecord will now cache its primary key rather than constantly regenerate.

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.

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

Better compatibility with FireFox 3's more aggressive caching of Ajax requests.

AjaxModalContainer supports binding "action" even when ajax=true, so you can perform a component action prior to rendering the component content of your container.

BugTracker
BugTracker now include support for the audit trails.

Maven
Lots of work on the maven build files for Wonder. As I understand it, which I don't :), Wonder Maven builds "just work".

WO Adaptors
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.

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

ERXAbstractRestEntityDelegate subclasses can more easily provide support for custom "primary keys" to be generated and resolved by overriding _isEOID, _objectWithKey, and idForEO methods.