Jeff,
Thanks for your input. I agree that looping back through the dispatcher
would be wasteful. The subclass of ControllerSingleton could then read the
rest of the configuration (the node is passed to init()) and then it would
be responsible for instantiating and calling go() on the nested controllers.
Once these complete we return the String indicating the view to render and
Maverick rolls on as always.
My only concern is that the XSLT is going to be pretty tricky--but I'll dig
in.
Taavi, I like your controller ref/id idea, but I am going to start without
it just because I am not the XSLT pro I'd like to be. Hopefully we can
figure that part out once we get a prototype running.
For a start:
Our pre-transformation maverick.xml
---------------------------------------------------------------------
<command name="myCommand1">
<controller-pipeline>
<controller class="com.foo.Bootstrap" proceedOn="continue">
<view name="error" path="fatalErrorPage.jsp"/>
</controller>
<controller class="com.foo.Authenticate" proceedOn="continue">
<view name="displayLogin" path="login.jsp"/>
<view name="notAuthorized" path="notAuthorized.jsp"/>
</controller>
<controller class="com.foo.ModuleSpecific1" proceedOn="continue"/>
<controller class="com.foo.Command1"/>
</controller-pipeline>
<view name="success" path="myPage.jsp"/>
<view name="error" path="errorPage.jsp"/>
</command>
---------------------------------------------------------------------
needs to become the following valid maverick.xml: (seen by no one except
maverick itself)
---------------------------------------------------------------------
<command name="myCommand1">
<controller class="org.infohazard.maverick.flow.ChainingController">
<!-- special configuration read by ChaingingController -->
<chainedController class="com.foo.Bootstrap" proceedOn="continue">
<contextView name="error" id="contextualizedViewID00001"/>
</chainedController>
<chainedController class="com.foo.Authenticate" proceedOn="continue">
<contextView name="displayLogin" id="contextualizedViewID00002"/>
<contextView name="notAuthorized" id="contextualizedViewID00003"/>
</chainedController>
<chainedController class="com.foo.ModuleSpecific1"
proceedOn="continue"/>
<chainedController class="com.foo.Command1"/>
<contextView name=success" id="contextualizedViewID00004"/>
<contextView name=error" id="contextualizedViewID00005"/>
<!-- end special configuration read by ChainingController -->
</controller>
<view name="contextualizedViewID00001" path="fatalErrorPage.jsp"/>
<view name="contextualizedViewID00002" path="login.jsp"/>
<view name="contextualizedViewID00003" path="notAuthorized.jsp"/>
<view name="contextualizedViewID00004" path="myPage.jsp"/>
<view name="contextualizedViewID00005" path="errorPage.jsp"/>
</command>
---------------------------------------------------------------------
The most notable feature of this transformation is that all of Maverick's
view names have been replaced with a generated id which links the Maverick
views with the <contextView> elements. This is necessary to preserve the
context sensitivity of the view names given in the top-most snippet since
there all views names are associated with a particular chained controller
and may be reused and redefined in the context of another controller. For
example each chained controller may have a view named "error" each of which
pointed to a different JSP. This would be impossible to represent in our
transformed maverick.xml file since the result would be:
<command name="myCommand1">
<controller class="org.infohazard.maverick.flow.ChainingController">
<view name="error" path="errorPage1.jsp"/>
<view name="error" path="errorPage2.jsp"/>
<view name="error" path="errorPage3.jsp"/>
<view name="success" path="myPage.jsp"/>
</command>
which would look like a configuration error to the Loader/Dispatcher.
When ChainingController is initialized it reads in the nested configuration
data from maverick.xml. It also creates a Map of the view names given in
<contextView name=""> and the ids specified in <contextView id="">.
When a command mapped to the ChainingController hits the Dispatcher, the
Dispatcher calls ChainingController.go() as we would expect. The
ChainingController then instantiates the first "chained" controller and
calls its go(). If the String result matches the "proceedOn" attribute, the
next controller is instantiated, etc. Otherwise ChainingController hands the
Map the String result of the "chained" controller's go() and gets a view id
back which it returns. Maverick then renders the view as it normally would.
This approach would be relatively transparent to the Maverick developer. The
developer could continue to use existing controllers (i.e. chained
controllers do not require a new interface or base class), and he would
simply alter his maverick.xml to look like the top most one and use
Maverick's native ability to transform maverick.xml using our style sheet.
This approach is also requires no known changes to Maverick itself but
simply adds a Controller (ChainingController) to the flow package. We'd
obviously want to slip the XSL into the distribution and some doc updates as
well--perhaps even a friendbook version.
So what does everyone think?
John-Mason Shackelford
Software Developer
NCS Pearson - Measurement Services
2510 North Dodge St.
Iowa City, IA 52245
319-354-9200x6214
[EMAIL PROTECTED]
-----Original Message-----
From: Schnitzer, Jeff [mailto:[EMAIL PROTECTED]]
Sent: Wednesday, January 22, 2003 3:44 PM
To: [EMAIL PROTECTED]
Subject: RE: [Mav-user] controller chaining; more discussion #3
Interesting thread!
With the XSLT transformation of the config file, it should be pretty easy to
experiment with these patterns.
I have mixed opinions about using controller chaining so extensively. I
can't imagine the performance cost of all the RequestDispatcher forwards is
a good thing.
Why not use the ControllerSingleton base and use the init() method to set up
your own composition scheme?
<command name="foo">
<controller class="blah.ComposedController">
<component class="blah.ComponentOne"/>
<component class="blah.ComponentTwo"/>
</controller>
</command>
You would have to define the interfaces for your composition scheme, but
this can be tailored a lot easier than trying to force everything through
the Dispatcher.
Jeff Schnitzer
[EMAIL PROTECTED]
-------------------------------------------------------
This SF.net email is sponsored by: Scholarships for Techies! Can't afford IT
training? All 2003 ictp students receive scholarships. Get hands-on training
in Microsoft, Cisco, Sun, Linux/UNIX, and more.
www.ictp.com/training/sourceforge.asp
[INVALID FOOTER]
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
[INVALID FOOTER]