cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Oliver <res1c...@verizon.net>
Subject Re: [RT] FOM
Date Tue, 27 May 2003 15:08:40 GMT
Stefano Mazzocchi wrote:

>Please, consider that even if I'm writing this, the ideas presented on
>this RT were distilled over several evenings spent with Ricardo on the
>whiteboard. As so, we are presenting them to you, hoping to sparkle
>further discussion.
>
>                                  - o -
>
>The FOM is the Flow Object Model. In my vision, it's the server-side
>equivalent of the DOM.
>
>Pier and I already stated a while back that our current implementation
>of the FOM is weak and its design poor. I had those feelings but I
>couldn't really come up with a real design reason for that, but now I
>have it: the current object model tries to wrap around everything
>without considering if it's good or bad to have access to the
>environment hooks.
>
>I believe that the number of methods/properties/objects should be
>reduced to the minimum necessary. Why so? several reasons:
>
> 1) incremental evolution: adding a method because something we thought
>it wastn't needed becomes needed doesn't create back-incompatibilities,
>removing a method because we find out how much it can be abused, it does.
>
>[NOTE: the sitemap has been designed with 'less is more' and every
>addition has been challenged deeply. Today, everybody sees the sitemap
>as an elegant and coherent contract]
>
> 2) design for safety: the flow will be a center of abuse because people
>will find it easier to write longer flows than to restructure their
>business logic into components. We must make all possible efforts to
>reduce this from happening.
>
>                             - o -
>
>First of all, as a general rule and in order to keep a sort of object
>orientation, no global methods or properties are kept. The only global
>contract is the "cocoon" object which is used as an entry point between
>the flow and cocoon. [this is equivalent of the "window" object for DOM]
>
>---------------------------------------------------------------------------
>The Cocoon Object
>---------------------------------------------------------------------------
>
>The Cocoon object is the only possible way the flow can communicate with
>Cocoon. In a sense, it's a gateway between the two realms. This protects
>the flow from abusing the Cocoon internals (for example, there is no way
>the flow can compose a sitemap pipeline since the cocoon object doesn't
>give it that power)
>
>--------- methods ------------
>
> void sendPage(uri,map) -> returns control to the sitemap, invoking the
>pipeline that will match the given URI and passing the given map as model.
>
> void sendPageAndWait(uri,map) -> same as above, but creates one (or
>more) continuation objects and makes their IDs available as part of the
>model passed.
>
> void processPipelineTo(uri,map,outputStream) -> invoques the pipeline
>that will match the given URI, passing the map as the model but
>connecting the output of the pipeline to the given output stream.
>
> void redirectTo(uri) -> triggers a client-side redirect to the given URI
>
> void addEventListener(eventName,eventHandler) -> adds an event listener
>to the given event name (for example, session expiration)
>
> void removeEventListener(eventName,eventHandler) -> removes the given
>handler from listening the tiven event name.
>
> Object getComponent(id) -> obtains the component indicated by the given ID
>
> void callAction(name,map) -> invoques the action indicated by the given
>name and pass the given map as model
>
>NOTE: I personally believe that the getComponent() method removes all
>needs for the callAction() method. I foresee a future where the
>callAction() method will be deprecated. I would personally go the extra
>mile and avoid having it there altogether, but since there is no easy
>way to plugin new avalon components at runtime (at least, not as easier
>as plugging in different actions into the sitemap), I'm in favor of
>leaving it for now, until 'real blocks' will make it unnecessary.
>
> Session getSession()
>
>NOTE: both Ricardo and I believe that the flow should always be
>associated with a Session. Thus the use of the semantics "getSession"
>instead of "createSession". 
>
It does seem unlikely that you could write a useful complete application 
using continuations alone.

>We are, in fact, against the concept of
>having the flow behave differently we the session has been created or
>it's has not been. This implicit behavior is potentially very dangerous
>from a user perspective and should be avoided.
>  
>
Dangerous in what way?

>Moreover, it has been pointed out how continuations can be see as a way
>to "extend" sessions rather than replacing them. This would allow us to
>reuse the session-handling machinery already in place for things like
>load-balancing and fault-tollerance.
>
Continuations are difficult to make serializable because they include 
everything reachable from your script. If you have access to one single 
object that isn't serialiazable, then kaboom.

>
>NOTE: methods that were left out where
>
> - input/output module support
> - script load support
>
>the reason for the first goes together with callAction(). Input/output
>modules were designed to overcome limitations in the scriptability of
>the sitemap.
>
>The reason for removing load() is because we want to avoid people from
>loading scripting dynamically. This goes in parallel with the
>anti-pattern of dynamic pipeline construction.
>
>WARNING: removing load() does *NOT* imply that you have to force all
>your flow in one big file. The way to fragment your flow into different
>files is to use several <map:script> elements in the <map:flow> section
>of the sitemap.
>
Agree with Sylvain that load() is needed to create reusable script 
components for use in flowscripts.

>
>-------- properties ---------
>
> cocoon.request -> the request object
> cocoon.response -> the response object
> cocoon.log -> the log object
>
>NOTE: the absence of the context object is intentional! we couldn't come
>up with a reasonable need for such an object at the flow level. So, for
>the principle of 'less is more', we don't consider it. Be aware that if
>you want to propose its addition, you have to come up with a reason for it.
>
>
>---------------------------------------------------------------------------
>The Session Object
>---------------------------------------------------------------------------
>
>The session object is simply a wrapper around the Session object
>provided by the Cocoon environment. No methods were left out since they
>don't provide problems to the flow environment or suggest abuse.
>
>---- methods -----
>
>attributes
> getAttribute(name)
> setAttribute(name,value)
> removeAttribute(name)
> getAttributeNames()
>
>control
> invalidate()
> isNew()
> getId()
>
>time
> getCreationTime()
> getLastAccessedTime()
> setMaxInactiveInterval(interval)
> getMaxInactiveInterval()
>
>---- properties -----
>
> [name] -> maps to the attribute indicates with the name
>
>For example
>
> session.blah
>
>is equivalent to
>
> session.getAttribute("blah")
>
>
>---------------------------------------------------------------------------
>The Response Object
>---------------------------------------------------------------------------
>
>The response object contains hooks only to the cookies and to the
>response headers. Everything else will be controlled by the rest of the
>cocoon pipeline machinery (like output encoding, for example, which
>should *NOT* be determined by the flow)
>
>------- methods -------
>
>cookies
>  Cookie createCookie(name,value)
>  void addCookie(Cookie cookie);
>
>headers
>  containsHeader(name)
>  setHeader(name,value)
>  addHeader(name,value)
>
>------- properties -----
>
>NONE
>
>
>---------------------------------------------------------------------------
>The Cookie Object
>---------------------------------------------------------------------------
>
>This object is a wrapper around the Cookie object provided by the
>Environment.
>
>--------- methods -------
>
> getName()
> getVersion()
> setVersion(version)
>
>values
> setValue(value)
> getValue()
>
>comment
> setComment(purpose)
> getComment
>
>domain
> setDomain(domain)
> getDomain()
>
>age
> setMaxAge(age)
> getMaxAge()
>
>path
> setPath(path)
> getPath()
>
>secure
> setSecure(secure)
> getSecure()
>
>-------- properties ------
>
> NONE
>
>---------------------------------------------------------------------------
>The Request Object
>---------------------------------------------------------------------------
>
>The Request object is the one who has been pruned the most from the
>Cocoon Environment. The sections that were pruned were:
>
> - URI handling
> - Session handling
>
>Session handling has been removed in favor of the cocoon object and URI
>handling has been removed because unnecessary. I'm aware this is a big
>statement, please see below of why this is so.
>
>----- methods ------
>
>attributes
> get(name)
> getAttribute(name)
> getAttributeNames()
> setAttribute(name,value)
> removeAttribute(name)
>
>encoding
> getCharacterEncoding()
> setCharacterEncoding(encoding)
>
>payload
> getContentLength()
> getContentType()
>
>parameters
> getParameter(name)
> getParameterValues(name)
> getParameterNames()
>
>transport
> getAuthType()
> getProtocol()
> getScheme()
> getMethod()
> getServerName()
> getServerPort()
> getRemoteAddr()
> getRemoteHost()
> isSecure()
>
>locale
> getLocale()
> getLocales()
>
>cookies
> getCookies()
>
>headers
> getHeader()
> getHeaders()
> getHeadersNames()
>
>authentication
> getRemoteUser()
> getUserPrincipal()
> isUserInRole(role)
>
>-------- properties ---------
>
> [name] -> maps to the parameter indicates with the name
>
>For example
>
> request.blah
>
>is equivalent to
>
> request.getParameter("blah")
>
>---------------------------------------------------------------------------
>The Log Object
>---------------------------------------------------------------------------
>
>This is a convenience method to access the cocoon logger. It could be
>the same of doing
>
> cocoon.getComponent(...)
>
>but since I removed the global print() method, I wanted to have an easy
>way to log (mostly for debugging purposes).
>
>------- methods --------
>
> debug(message)
> info(message)
> warn(message)
> error(message)
>
>------ properties ------
>
> NONE
>
>                                --- o ---
>
>That's it.
>
+1 (with the exception of removing "load()").

Chris


Mime
View raw message