Carsten Ziegeler wrote:
Our request object is modelled after the request object of the servlet spec. Now this approach is not bad, but Cocoon has something which the servlet spec does not have: internal requests. Unfortunately, our api does not take this into account.
URIs ---- The request has currently two methods for the URI: getRequestURI and getSitemapURI.
For external requests, getRequestURI returns the original
URI and getSitemapURI contains the part of the uri that has
entered the current sitemap. So these values differ as soon as you use sub sitemaps with removing the prefix.
Now, for internal requests the situation is not as good: getRequestURI returns the uri of the original/external request and getSitemapURI again contains the part of the internal requests URI that has entered the current sitemap. So, with internal requests you have no chance to get the full internal URI as soon as you moved into a subsitemap. This is imho bad. Obviously, we can't change getRequestURI() for internal requests as this would break compatibility.
One possibility would be to introduce a new method: getSitemapPrefix() which returns the prefix for the current sitemap, so this is the empty string for the main sitemap and the prefix for sub sitemaps.
This would mean for external requests: getRequestURI = getSitemapPrefix() + getSitemapURI()
and for internal requests: URI of internal request = getSitemapPrefix() + getSitemapURI()
(We already have this prefix in the environemnt, so we just have to make it available).
Big +1 , but what about naming it getSitemapPath() to mimic HttpServletRequest.getServletPath()?
Attributes ----------
We have a similar problem with attributes on the request object. Currently the attributes are shared between external and internal requests, making them "global". So, an internal request can overwrite attributes of the external request and of other internal requests. This can lead to serious problems especially if you have several internal requests at the same time using the same attribute - or if you want to process internal requests in parallel.
Again, because of compatibility, we can't change this behaviour. But we can extend it. Currently we have these methods for attributes that work on global attributes:
setAttribute(String, Object) getAttribute(String) getAttributeNames() removeAttribute(String)
We could add another set of methods that take an additional scope parameter which is either "global" or "request" (like the portlet api does for session attributes):
setAttribute(String, Object, int scope) getAttribute(String, int scope) getAttributeNames(int scope) removeAttribute(String, int scope)
Our old method (without the scope) are simply an alias for the
new methods with the scope "global".
I was recently looking at flowscript within coplets, and thought this scope should better be defined by the surrounding caller, i.e. by a coplet parameter. That way, the request providing coplet contents doesn't have to care whether it's used withing a coplet or not, which can be especially useful to "portalize" application modules not initially designed with these problems in mind.
Of course, there are cases where we need to mix both kind of scopes, and the coplet attribute could therefore be used to define the default scope if not specified.
Cleanup of Attributes --------------------- Currently there is no nice way to cleanup some objects when the processing is finished. This only works for components that are pooled/recycled but not for data objects.
With 2.1.5 you could do this by adding a custom listener to the Cocoon
object and clean up. But this approach is not so nice as you can only
add one listener and you have to do it manually. And the listener
is not invoked for internal requests.
Uh? Didn't knew about this feature!
With Cocoon 2.1.x users have used the RequestLifecycle and GlobalRequestLifecycle components that cleaned up the data after the request has been processed. We deprecated these components and removed them for 2.2.x. In general, the RL and GRL components were a nice idea, but in most cases not the component but the data should have been linked to a request, so finding a better solution was a logical step.
At that time the basic idea was that the current RequestDataStore
component takes over this role, but it does't provide the cleanup
yet and it seems to be a little overkill for such a simple thing.
With the additional scope parameter for request attributes explained above, there is no need for a RequestDataStore component anymore.
The only piece missing is cleaning up of data when the request is finished. This feature has been requests in the last months several times from users :)
Now, the basic mechanism for this could be to scan all attribute values of the request and find out if the value should be cleaned up or not. This could be done by either testing for the usual suspects from Avalon (Disposable, Recyclable) or by defining a new Cocoon specific interface.
But perhaps there is a better way?
What about adding a list of ProcessingListeners to the object model, which can be augmented by the various components that participate in request handling, and is called at particular places such as:
- processing start (such listeners must be registered in the xconf),
- sitemap mount,
- end of pipeline building,
- start of pipeline execution (differs from the previous one as it may not be called if the result is cached)
- end of pipeline execution
- end of processing
That would allow e.g. a flowscript to register a listener that closes a hibernate session once the processing is terminated, thus allowing the same session to be used in the view.
Sylvain
-- Sylvain Wallez Anyware Technologies http://www.apache.org/~sylvain http://www.anyware-tech.com { XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
