March 26, 2004

Cocoon Forms in Portal Environment

Those who worked with Portal and Portlets (and here I mean JSR-168 portlets), they know that Portlet has two kind of requests: RenderRequest and ActionRequest. These two requests can be compared with regular servlet's GET and POST requests, but there is significant difference: Portlet's ActionRequest can not have any response body!

This means, that the approach (GET request shows form - Submit POSTs form to server - server validates form and in case of failure re-displays form) taken by Cocoon Form's showForm() method is not possible anymore. Once form is POSTed (or, ActionRequest is received - in Portlet-speak), response can not be HTML of the re-displayed form, response must be always redirect, and only subsequent RenderRequest can send HTML with re-displayed forms.

To achieve this functionality, Form.showForm() method should be overridden:

Form.prototype.showForm = function(uri, bizData) {
    // ... Snip ...
    var finished = false;
    this.isValid = false;

    var s = capture();
    var k = cocoon.sendPageAndWait(uri, bizData);
    var formContext = Packages.org.apache.cocoon.woody.flow.javascript.
        WoodyFlowHelper.getFormContext(cocoon, this.locale);

    // Prematurely add the bizData as a request attribute so that event listeners can use it
    // (the same is done by cocoon.sendPage())
    cocoon.request.setAttribute(
        Packages.org.apache.cocoon.components.flow.
            FlowHelper.CONTEXT_OBJECT, bizData);

    finished = this.form.process(formContext);

    // Additional flow-level validation
    if (finished && this.form.isValid()) {
        if (this.validator == null) {
            this.isValid = true;
        } else {
            this.isValid = this.validator(this.form, bizData);
            finished = this.isValid;
        }
    }

    if (!finished) {
        // Failure: Redirect back to starting point, s.
        cocoon.redirectTo(s.id + ".continue");
        FOM_Cocoon.suicide();
    }

    var widget = this.form.getSubmitWidget();
    // Can be null on "normal" submit
    this.submitId = widget == null ? null : widget.getId();

    // Success: Redirect out of this function
   cocoon.redirectTo(cocoon.makeWebContinuation(new Continuation()).id + ".continue");
    FOM_Cocoon.suicide();
}

Where, capture() method is simply:

function capture() {
    var wc = cocoon.createWebContinuation(0);
    return wc;
}

PS All of the above relevant when using Cocoon Forms (a.k.a. Woody) from the Flow.

Posted by Vadim at March 26, 2004 8:45 AM