Gianugo Rabellino wrote:

We are currently building a cforms based application with fairly decent complexity level. Our (rather convoluted but, take my word for that, legit) business logic requires the usage of an Avalon component during the binding phase, so we thought to use the fb:javascript binding method, hoping to find (even if not explicitely documented) the good old FOM, together with the cocoon object.

That was indeed the case, and we were cheerfully using logic like the one in the following snippet:

<fb:load-form>
   var validation = cocoon.getComponent("bindinghelper");
   var today = new Packages.java.util.GregorianCalendar();
   var executionDate = validation.getValidExecutionDate(today);
   widget.setValue(executionDate.getTime());
</fb:load-form>

At a certain point, though, we mangled the form *definition* and modified a selection list so that it was taking its data from a cocoon:/ pipeline instead than from a static file (which we used during prototyping). Such pipeline, in turns, calls the flow which sendPage()s to a JXTG (data are in a business object we need to stream):


<snip/>

I found the cause of the problem.

The flowscript scope is stored in a request attribute (see FOM_JavaScriptFlowHelper) and this attribute is cleared upon termination of the script execution to prevent any further usage after the script execution is finished.

The problem comes from the fact that request attributes are shared between the "real" request and all internal requests that are created to answer the real one. This means that when your selection list pipeline is executed :
1/ the original scope (from form.showForm) is overriden by the scope for the selection list
2/ when the selection list has been generated, the request attribute is cleared, and there is therefore no more "cocoon" object in the request for subsequent js bindings.


The solution is to use a storage means that is independent for each of the various internal requests used to produce the response. In Cocoon, this is the object model. It also has the additional benefit that a child requests starts with a copy of the parent's object model and locally overrides it (works like InheritableThreadLocal)

The problem is potentially the same for every other data issued by the flowscript (continuation, view data, request, etc).

I modified FlowHelper and FOM_JavaScriptFlowHelper so that they use the object model. I also moved to private all static strings defining storage keys as I found some direct references to them to store data as request attributes that violate the encapsulation provided by the setters in these two classes. This may cause incompatibilities in external code that does the same, but there's no way around it if we want the use of setters to be enforced, which hides the storage location for this data.

This should solve your problem. Please cross-check!

Sylvain

--
Sylvain Wallez                                  Anyware Technologies
http://www.apache.org/~sylvain           http://www.anyware-tech.com
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }



Reply via email to