You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by Don Brown <mr...@twdata.org> on 2005/08/31 22:34:23 UTC
Re: Spring and XWork in Ti
Joe Germuska wrote:
> So, I really do have work I should be doing, but I couldn't help looking
> around XWork a little bit, and I'm just wondering why Ti needs to use
> both it and Spring anyway?
>
> What are the various services offered by each that aren't offered by the
> other?
I should really list this out on the wiki site. The short of it is XWork gives us an Action framework, interceptor
chains, expression language support, l18n, validation, and the value stack. WebWork gives us all their result types and
neat tag libraries that can be used with any template technology.
I like working with XWork and WebWork2 because it is similar enough to Struts classic that we can provide near
backwards-compatibility, yet it is written very well, and brings a bunch of new features we can get for free.
Furthermore, I think there is a lot of synergy to be had between the two teams for each to explore new features that can
be easily shared back and forth.
Don
>
> Joe
>
>
> At 2:44 PM -0500 8/31/05, Joe Germuska wrote:
>
>> I don't know anything about how XWork will handle message resources,
>> but what I'm talking about is all internal to Struts anyway, so I'm
>> not sure that the user needs to be concerned; this is more about an
>> alternative to all the LocalStrings.properties files which Struts
>> classes currently have to bootstrap themselves.
>>
>> Until I see it, I won't argue very hard for using Spring as the
>> message resolver, but I am finding it handy inside my own
>> applications. Are there any places in Struts Ti where XWork's message
>> facilities are being used?
>
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Don Brown <mr...@twdata.org>.
At this stage in the project, we are exploring problems and solutions. It can
be misleading to follow the dev discussion thinking this is what the user will
need to know and understand in order to use the project. Each of the components
discussed here are solutions to problems. What Ti is trying to determine is
what problems it will tackle and what components already provide solutions.
In the end, I envision the average Struts developer not knowing or caring about
90% of this stuff. They will write Controller classes, annotated with tags that
request validation, views, etc., then Ti will take care of it from there. My
goal is for the user to not even know they are using XWork, just that when they
add the @ti.action annotation, they can call that action from a URL. If they
want validation, they add a @ti.validationRequired tag. They shouldn't know or
care if it is commons-validator under the covers that does the work or XWork
validations.
This level of user abstraction, I feel, hasn't been a priority for many projects
and causes confusion. I'm tired of the confusion caused by Struts apps being a
mix of Tiles, commons-validator, Struts, Beanutils, etc., and those are just the
out-of-the-box components Struts ships with. Some projects like Tapestry solve
this by rolling their own IoC, HTML template language, component model, etc., to
present a unified face to the developer. I'm hoping to also provide a simple,
unified framework to the developer, but take advantage of all the hard work
folks have put into projects like Spring, WebWork, Beehive, etc. under the covers.
This may not be a reachable goal, but I'm hoping we can give it a shot.
Don
netsql wrote:
> As MF says: "Comprehensiveness is the enemy of comprehensibility".
>
> To that end, if there is a way to have one, but not both, it's a plus.
>
> Spring + CoR + WebWork + XYZ... that looks scary (and still not
> defulting to "Ajax").
>
> Don, If you like IoC, lets start w/ HiveMind (or whatever IoC + iBatis
> DAO) and ignore CoR, and build clean and build for Ajax example of the
> bat (the 2 Ajax libs that MC talks about, and then rig Faclets or
> whatever else later, that would give us a sweet spot).
>
> It has to be teachable at the end.
>
> .V
>
>
> Ted Husted wrote:
>
>> My only point would be that these tools seem close enough that we
>> should be able to extend one to fill the role of the other.
>>
>> --
>
>
> Broadband interface (RIA) + mail box safety = Roomity.com
> <http://roomity.com/demo.jsp>
> *Your* clubs, no sign up to read, ad supported; try broadband internet.
>
> cell: 917 825 3035 in DFW
> email: netsql at roomity.com
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> For additional commands, e-mail: dev-help@struts.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by netsql <ne...@roomity.com>.
As MF says: "Comprehensiveness is the enemy of comprehensibility".
To that end, if there is a way to have one, but not both, it's a plus.
Spring + CoR + WebWork + XYZ... that looks scary (and still not
defulting to "Ajax").
Don, If you like IoC, lets start w/ HiveMind (or whatever IoC + iBatis
DAO) and ignore CoR, and build clean and build for Ajax example of the
bat (the 2 Ajax libs that MC talks about, and then rig Faclets or
whatever else later, that would give us a sweet spot).
It has to be teachable at the end.
.V
Ted Husted wrote:
> My only point would be that these tools seem close enough that we
> should be able to extend one to fill the role of the other.
>
>--
Broadband interface (RIA) + mail box safety = Roomity.com
<http://roomity.com/demo.jsp>
*Your* clubs, no sign up to read, ad supported; try broadband internet.
cell: 917 825 3035 in DFW
email: netsql at roomity.com
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Ted Husted <te...@gmail.com>.
Well, that is pretty cool. But, using Chain, I wouldn't use a filter.
I'd define two commands, one to start the timer and one to stop the
timer. The timer would go into the context, which is thread-safe.
Then wherever we wanted to use the timer commands, we'd turn the
command into a chain (if it already wasn't).
So, if we had something like
<object id="issue_select" parent="BaseSelect">
<property name="Input">
<list>
<value>issue_key</value>
</list>
</property>
<property name="Output">
<list>
<value>issue_code</value>
<value>issue_type</value>
</list>
</property>
</object>
we'd just make turn it into a chain
<object id="issue_select" parent="BaseChain">
<property name="AddCommands">
<list>
<ref object="timer_stop" />
<ref object="issue_select_core" />
<ref object="timer_start" />
</list>
</property>
</object>
<object id="issue_select_core" parent="BaseSelect">
<property name=input">
<list>
<value>issue_key</value>
</list>
</property>
<property name="output">
<list>
<value>issue_code</value>
<value>issue_type</value>
</list>
</property>
</object>
If we wanted to time everything, we'd add them to the aforementioned
pre/post chains instead.
If such things were happening all the time, we could also add pre/post
chains to the base command processing. If the before and/or after
properties were present on the command, the processor could create a
dynamic chain to include them.
<object id="issue_select" parent="BaseSelect">
<property name="Input">
<list>
<value>issue_key</value>
</list>
</property>
<property name="Output">
<list>
<value>issue_code</value>
<value>issue_type</value>
</list>
</property>
<property name="AddBefore">
<list>
<list>
<ref object="timer_start" />
</list>
</property>
<property name="AddAfter">
<list>
<list>
<ref object="timer_stop" />
</list>
</property>
</object>
So, where WebWork added chain processing to the interceptor, we could
add interception to the chain processing. :)
My only point would be that these tools seem close enough that we
should be able to extend one to fill the role of the other.
Of course, that might be something better decided once there is a
working framework to try stuff with. :)
-T.
On 9/1/05, Don Brown <mr...@twdata.org> wrote:
> Perhaps an example would help convey what I'm trying to say:
>
> Take a simple case where you want to processing time and log it to a file. As a
> XWork interceptor, it would look like this:
>
> long startTime = System.currentTimeMillis();
> String result = invocation.invoke();
> long executionTime = System.currentTimeMillis() - startTime;
> log.info("Execution time: "+executionTime+" ms");
>
> Here, we define a method variable, startTime, before the rest of the execution,
> then need to access it after the execution is done.
>
> If we wanted to write this as a Filter in commons-chain, we couldn't without
> making startTime a class level variable, but then the command would no longer be
> thread-safe.
>
> Ah, but you might suggest we write that as a chain since a chain has explicit
> control over executing its children. But then, we'd have to define the rest of
> the commands within that chain and if you have multiple commands like this timer
> command, they too would have to be chains:
> process-chain
> timer-chain
> fooCommand
> otherAroundCommand
> barCommand
> ....
>
> This obviously has the disadvantage of deep nesting losing some of the
> readability of a simple process chain.
>
> Therefore, my point is an interceptor chain is better suited to a scalable,
> linear process flow, while chain is better for decision points. And neither,
> I'd argue, is well suited for a robust, configurable workflow, and this surely
> we can agree we are seeing with commons-chain in Struts Classic.
>
> Don
>
> BTW, I'm really enjoying this discussion and have missed these on this list.
>
> Ted Husted wrote:
> > On 9/1/05, Don Brown <mr...@twdata.org> wrote:
> >
> >>In that case, I find interceptors more practical, as they allow
> >>you to have code before and after processing that uses method variables. With
> >>Chain, you have to use a Filter and even then, there is no way to share
> >>variables between the two blocks of code without instance variables which has
> >>its own problems.
> >
> >
> > First, you're doing the work, Don, and so you're welcome to make the
> > decisions :)
> >
> > Though, I don't understand is why you'd want to be restricted to two
> > blocks of code :)
> >
> > With Chain, any number of blocks of code, be they commands or chains,
> > in any combination, can be the object of the request processing.
> >
> > In OverDrive/Nexus, we do find having interceptors that surround each
> > request useful. It's not hard to define "pre" and "post" chains, and
> > then at runtime create a third chain to execute them all.
> >
> > public void ExecuteView (IRequestContext context)
> > {
> > IRequestCommand command = VerifyRequest (context);
> > if (context.IsNominal)
> > {
> > IChain chain = new Chain ();
> > if (_PreOp!=null) chain.AddCommand (_PreOp);
> > chain.AddCommand (command);
> > if (_PostOp!=null) chain.AddCommand (_PostOp);
> > try
> > {
> > chain.Execute (context);
> > }
> > catch (Exception e)
> > {
> > context.Fault = e;
> > }
> > }
> > }
> >
> > http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/overdrive/Nexus/Extras/Spring/Catalog.cs?view=markup
> >
> > The PreOp and PostOp chains are defined in the configuration, along
> > with everything else.
> >
> > But, we're not trying to solve the problems of navigational workflows,
> > only the problem of processing business use cases and interacting with
> > a presentation layer
> >
> > -Ted.,
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> > For additional commands, e-mail: dev-help@struts.apache.org
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> For additional commands, e-mail: dev-help@struts.apache.org
>
>
--
HTH, Ted.
http://www.husted.com/poe/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
OT: Re: Spring and XWork in Ti
Posted by netsql <ne...@roomity.com>.
Ted Husted wrote:
.
>
> Many other .NET applications ...
Here is one C# ex:
http://www.castleproject.org/movies/CoR_Overview_Smallmod.htm
--
thx,
.V
Broadband interface (RIA) + mail box safety = Roomity.com
<http://roomity.com/demo.jsp>
*Your* clubs, no sign up to read, ad supported; try broadband internet.
cell: 917 825 3035 in DFW
email: netsql at roomity.com
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Ted Husted <te...@gmail.com>.
On 9/2/05, Don Brown <mr...@twdata.org> wrote:
> Ted Husted wrote:
> > Well, in the spirit of discussion ...
> >
> > An important consideration is where to put the composition. We haven't
> > figured out how to use the Spring.Web wizards yet, so for our .NET
> > apps we've been decomposing the "pages" or "dialogs" into User
> > Controls. The actual ASPX page then becomes a list of controls that
> > the workflow might use.
>
> That's a very interesting approach, so in effect, your page behind becomes your
> "Controller" containing multiple page actions. I wonder how/if that would
> translate to JSF. Reminds me of the folks that are doing pure client-side, one
> url apps, using javascript to handle page navigation.
Yes. I expect that the approach would port, given the similarities
between the platforms.
Many other .NET applications do the same sort of thing, but typically
use a "placeholder" control in the page to swap other controls in and
out. Swapping seems to work well enough, but code-behind logic can get
hoary, especiallly when people try to use one page to serve the entire
application. The placeholder approach also makes the application
harder to "discover" for someone just wandering through the code.
Under the container page approach, you can look at the page and see
what User Controls are involved. It's also very easy to pass values,
since the components are all live. We just have to be careful to not
let the list components save large lists, which encumbers the page
state.
When we do need to jump between pages, Spring.WEB has a very nice
"ActionForward" like component.
* http://opensource2.atlassian.com/confluence/spring/display/NET/Result+mapping
For the business logic, we inject a "ViewHellper" into the page that
encapsulates the Context and Command into a single facade. Typical
calls look like
public void Open()
{
if (IsPostBack) return;
IViewHelper helper = ExecuteBind(App.ROUTING_FIND);
if (!helper.IsNominal()) Page_Error = helper;
}
Line 2 executes the command named "routing_find", and then binds the
result values to the UI controls.
Line 3 asks the helper if all went well, and if not, hands the helper
to the Page_Error property. This "property" actually fires an event
handler, which passes the helper to to the containing page, which
displays the message.
Any manner of error could be displayed here, including system errors
coming back from the database.
----
private void find_Click(object sender, EventArgs e)
{
if (Click == null) return;
IViewHelper helper = Read(App.ROUTING_FIND);
if (helper.IsNominal())
Click(this, new ViewArgs(helper));
}
Here, line 2 reads values input by the user. If all goes well, line 3
throws a Click event to be caught by the containing page.
----
protected IViewHelper save_Changes()
{
IViewHelper helper = ReadExecute(App.FACILITY_SAVE);
if (helper.IsNominal()) Page_Reset();
else Page_Error = helper;
return helper;
}
Line 1 reads values input by the user, and then executes the
"facility_save" command. Depending on whether everything worked, the
second statement either resets the UI controls, or displays any
messages. The helper is returned to the caller, in case further
processing is needed.
----
In case anyone is interested, I posted a copy of our internal User
Control RFC here:
* http://husted.wush.net/docs/display/NEO/RFC+-+User+Controls
-Ted.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Don Brown <mr...@twdata.org>.
Ted Husted wrote:
> Well, in the spirit of discussion ...
>
> An important consideration is where to put the composition. We haven't
> figured out how to use the Spring.Web wizards yet, so for our .NET
> apps we've been decomposing the "pages" or "dialogs" into User
> Controls. The actual ASPX page then becomes a list of controls that
> the workflow might use.
That's a very interesting approach, so in effect, your page behind becomes your
"Controller" containing multiple page actions. I wonder how/if that would
translate to JSF. Reminds me of the folks that are doing pure client-side, one
url apps, using javascript to handle page navigation.
Don
>
> <HTML>
> <body>
> <spring:Content contentPlaceholderId="cphMain" id="cphMainContent"
> runat="server">
>
> <wqd:RoutingMerger id="routing_merger" Runat="server"></wqd:RoutingMerger>
>
> <wqd:RoutingEditor id="routing_editor" Runat="server"
> OnQuit="routing_editor_Quit"
> OnSave="routing_editor_Save"></wqd:RoutingEditor>
>
> <wqd:FacilityEditor id="facility_editor" Runat="server"
> OnQuit="facility_editor_Quit"
> OnSave="facility_editor_Save"></wqd:FacilityEditor>
>
> <wqd:FacilityLister id="facility_lister" runat="server"
> OnAdd="facility_lister_Add"
> OnClick="facility_lister_Click"></wqd:FacilityLister>
>
> <wqd:FacilityFinder id="facility_finder" Runat="server"
> OnClick="facility_finder_Click"></wqd:FacilityFinder>
>
> </spring:Content>
> </body>
> </HTML>
>
> Running from the bottom, this particular page displays a "Facilty
> Finder". Once the user enters some search criteria, the result is
> displayed by the "Facility Lister". Here they can branch to a Facility
> Editor, to add or edit a Facility, or go on to the Routing Editor. The
> Routing Editor collects details for a "Routing Sliip", which can then
> be merged into Word document, if the user choose.
>
> All the business and presentation logic for each step is encapsulated
> in the individual controls. We then use the page's code-behind to
> shepard the navigation. The code-behind makes the controls visible or
> invisible as needed, reacts to the registered events, and passes
> values between controls as needed. Each control has properties to
> represent the input and output values. Since the controls are external
> to the page, we can reuse the controls in other workflows.
>
> Here's the handler that grabs the search criteria and passes it to the
> Facility Lister:
>
> protected void facility_finder_Click(object sender, EventArgs e)
> {
> ViewArgs v = e as ViewArgs;
> facility_lister.list_Criteria = v.Helper.Criteria;
> facility_lister.Open();
> facility_lister.Visible = true;
> }
>
> The nice part is that we can focus on one thing at a time. If there's
> an issue with a control, we can edit just the control. If there's an
> issue with the navigation, we can focus on that, without all the
> control code clutter.
>
> To run the actual business logic, each control can access the object
> catalog, which contains our command Helpers and other goodies. The
> code-behinds for the controls collect the appropriate values, invoke
> the business commands, and call an event handler when they are done.
>
> The icing on the cake is that we have figured out how to use the
> Spring.Web master pages. So we don't need to include any chrome on the
> workflow pages. Aside from registering the tags, all we need is what's
> above. All the headers, footers, and menu stuff is in other "Tiles.".
>
> -Ted.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> For additional commands, e-mail: dev-help@struts.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Ted Husted <te...@gmail.com>.
On 9/1/05, Joe Germuska <Jo...@germuska.com> wrote:
> but that XML is not a very nice way to define everything that needs
> to happen, and object-level composition is also likely to be awkward
> for some of these kinds of things.
Well, in the spirit of discussion ...
An important consideration is where to put the composition. We haven't
figured out how to use the Spring.Web wizards yet, so for our .NET
apps we've been decomposing the "pages" or "dialogs" into User
Controls. The actual ASPX page then becomes a list of controls that
the workflow might use.
<HTML>
<body>
<spring:Content contentPlaceholderId="cphMain" id="cphMainContent"
runat="server">
<wqd:RoutingMerger id="routing_merger" Runat="server"></wqd:RoutingMerger>
<wqd:RoutingEditor id="routing_editor" Runat="server"
OnQuit="routing_editor_Quit"
OnSave="routing_editor_Save"></wqd:RoutingEditor>
<wqd:FacilityEditor id="facility_editor" Runat="server"
OnQuit="facility_editor_Quit"
OnSave="facility_editor_Save"></wqd:FacilityEditor>
<wqd:FacilityLister id="facility_lister" runat="server"
OnAdd="facility_lister_Add"
OnClick="facility_lister_Click"></wqd:FacilityLister>
<wqd:FacilityFinder id="facility_finder" Runat="server"
OnClick="facility_finder_Click"></wqd:FacilityFinder>
</spring:Content>
</body>
</HTML>
Running from the bottom, this particular page displays a "Facilty
Finder". Once the user enters some search criteria, the result is
displayed by the "Facility Lister". Here they can branch to a Facility
Editor, to add or edit a Facility, or go on to the Routing Editor. The
Routing Editor collects details for a "Routing Sliip", which can then
be merged into Word document, if the user choose.
All the business and presentation logic for each step is encapsulated
in the individual controls. We then use the page's code-behind to
shepard the navigation. The code-behind makes the controls visible or
invisible as needed, reacts to the registered events, and passes
values between controls as needed. Each control has properties to
represent the input and output values. Since the controls are external
to the page, we can reuse the controls in other workflows.
Here's the handler that grabs the search criteria and passes it to the
Facility Lister:
protected void facility_finder_Click(object sender, EventArgs e)
{
ViewArgs v = e as ViewArgs;
facility_lister.list_Criteria = v.Helper.Criteria;
facility_lister.Open();
facility_lister.Visible = true;
}
The nice part is that we can focus on one thing at a time. If there's
an issue with a control, we can edit just the control. If there's an
issue with the navigation, we can focus on that, without all the
control code clutter.
To run the actual business logic, each control can access the object
catalog, which contains our command Helpers and other goodies. The
code-behinds for the controls collect the appropriate values, invoke
the business commands, and call an event handler when they are done.
The icing on the cake is that we have figured out how to use the
Spring.Web master pages. So we don't need to include any chrome on the
workflow pages. Aside from registering the tags, all we need is what's
above. All the headers, footers, and menu stuff is in other "Tiles.".
-Ted.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Joe Germuska <Jo...@Germuska.com>.
At 12:41 PM -0700 9/1/05, Don Brown wrote:
>Hmm...well there are three main issues we are discussing here,
>although you mention at the end they do have some overlap:
>
>1. Framework-level request processing
>2. Action-level processing
>3. Application-level page flow/workflow
>
>When was referring to commons-chain being a poor match for workflow
>I was primarily talking about #1. Examples of this include how
>Struts Classic commands have all sorts of ugly logic in them to skip
>themselves if an object isn't found in the context. This seems
>fine...
I don't really think it seems fine, but I don't think this is endemic
to commons-chain; I think it's just a naive implementation of the
original translation of the RequestProcessor to commons-chain. (No
offense meant by the term "naive".)
That said, while I've had some ideas about how to do it better, I'm
not sold on any of them, so maybe commons-chain still doesn't deal
with this extremely well. And as I write this, I realize that your
point, Don, is that one could probably do it all with commons-chain,
but that XML is not a very nice way to define everything that needs
to happen, and object-level composition is also likely to be awkward
for some of these kinds of things. For example, a conditional lookup
command which dealt with 2..n possible branches would be difficult to
configure simply by setting bean properties upon a generic "branch
command". (At least, I think this is your point, or part of it...)
Still, Struts 1.3 could have a cleaner default RP chain, and I feel
that it exposes the RP process adequately for customization, but it
seems clear that it will still be at least a "journeyman" level task
for someone to make modifications to the chain, particularly given
how tightly coupled local modifications are to the Struts base
process. (It would be nice to have some "advice" like way to
decorate the chain, as with Maven preGoal and postGoal, but I haven't
thought of a way I'd propose to do that without substantially
reorganizing commons-chain's basic model. For a while Bob McWhirter
was distributing werkz, which I think is the core of Maven 1.x's
process, but that seems to have disappeared from werken.com or
codehaus.org.)
Joe
--
Joe Germuska
Joe@Germuska.com
http://blog.germuska.com
"Narrow minds are weapons made for mass destruction" -The Ex
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Don Brown <mr...@twdata.org>.
Hmm...well there are three main issues we are discussing here, although you
mention at the end they do have some overlap:
1. Framework-level request processing
2. Action-level processing
3. Application-level page flow/workflow
When was referring to commons-chain being a poor match for workflow I was
primarily talking about #1. Examples of this include how Struts Classic
commands have all sorts of ugly logic in them to skip themselves if an object
isn't found in the context. This seems fine until you step back and realize it
is very hard to see the overall process flow without digging into the source
code of each command. I'm not sure I have a solution to this problem so at the
moment, Ti uses commons-chain so that at least a user could override a step or
two in the process as needed.
Action-level processing is what I would consider basic services available for
action invocation and view processing, including form bean creation, population,
validation, logging, etc. Interceptors is a good design, I feel, for this
problem because you usually want a short, linear process/chain that may differ
per action, but generally be the same. There is no need for branching or states
here, as this could be considered a subset of Aspect-Oriented Programming.
Application-level page flow targets a different audience and presumably harder
problems including multi-request flows, and I would classify them as solving the
problem of what action or actions should be invoked per request. I would
include action and view processing in this flow. Solutions include:
1. Beehive's Page Flow
2. Spring's Web Flow
3. Cocoon's Control Flow
What I like about Beehive's Page Flow is it is annotation driven, and supports
advanced features like shared flows and inherited flows. Spring's Web Flow is
new to me, so I can't comment much other than it seems clean but difficult to
follow without a visualization tool. And for Cocoon and continuations in
general, I still think they are a great solution since the workflow is
implemented in code (Javascript, Java, Ruby, whatever), and furthermore, the
workflow is in one, easy to read location, generally one method/function.
I suppose it could be argued that all these could share the same tool, but, IMO,
each have their own requirements and deserve a specialized tool suited for their
use cases. Commons-chain could, perhaps, be used for these three types of
processing, but I fear it would be verbose and cumbersome.
Don
Craig McClanahan wrote:
> On 9/1/05, Don Brown <mr...@twdata.org> wrote:
>
> Therefore, my point is an interceptor chain is better suited to a scalable,
>
>>linear process flow, while chain is better for decision points. And
>>neither,
>>I'd argue, is well suited for a robust, configurable workflow, and this
>>surely
>>we can agree we are seeing with commons-chain in Struts Classic.
>
>
>
> I generally agree with this, and the other points Don has made in this
> thread ... and would suggest (sorry Don :-) that the same issue happens with
> continuations based architectures like Cocoon Webflow and Struts Flow. None
> of these approaches seem to deal with conditional branches in workflows very
> well.
>
> This is one of the reasons that I was initially enamored with Spring
> WebFlow's approach, which defines the processing logic as a series of
> states, linked by transitions. States can be action states (like calling
> Action.execute() in a Struts app) or view states (display a page, receive
> the subsequent form submit. All states return an outcome that can be used to
> drive the transition, so you can do branches very easily. Or, you can glue
> together any number of action states in sequence to get the fine grained
> sequential functionality that a chain provides.
>
> In Shale, this idea is encapsulated as a "dialog", which leverages the fact
> that JSF action methods already returned a String outcome (so that it fit
> naturally into the state transition model) -- I just added the idea of an
> action state represented as an expression that called some arbitrary method
> that also returned a String. This lets you do things like representing an
> entire workflow in an easy to understand configuration (or, equivalently, in
> a UML state diagram):
>
> <!-- Log On / Create Profile Dialog -->
> <dialog name="Log On"
> start="Check Cookie">
>
> <action name="Check Cookie"
> method="#{profile$logon.check}">
> <transition outcome="authenticated"
> target="Exit"/>
> <transition outcome="unauthenticated"
> target="Logon Form"/>
> </action>
>
> <view name="Logon Form"
> viewId="/profile/logon.jsp">
> <transition outcome="authenticated"
> target="Exit"/>
> <transition outcome="create"
> target="Create Profile"/>
> </view>
>
> <subdialog name="Create Profile"
> dialogName="Edit Profile">
> <transition outcome="success"
> target="Exit"/>
> </subdialog>
>
> <end name="Exit"
> viewId="/usecases.jsp"/>
>
> </dialog>
>
> Although the dialog facility is primary focused around multi-request
> workflows, you can leverage the same concepts for fine grained flows within
> a particular request.
>
> Craig
>
>
>
> Don
>
>>BTW, I'm really enjoying this discussion and have missed these on this
>>list.
>>
>>Ted Husted wrote:
>>
>>>On 9/1/05, Don Brown <mr...@twdata.org> wrote:
>>>
>>>
>>>>In that case, I find interceptors more practical, as they allow
>>>>you to have code before and after processing that uses method variables.
>>
>>With
>>
>>>>Chain, you have to use a Filter and even then, there is no way to share
>>>>variables between the two blocks of code without instance variables
>>
>>which has
>>
>>>>its own problems.
>>>
>>>
>>>First, you're doing the work, Don, and so you're welcome to make the
>>>decisions :)
>>>
>>>Though, I don't understand is why you'd want to be restricted to two
>>>blocks of code :)
>>>
>>>With Chain, any number of blocks of code, be they commands or chains,
>>>in any combination, can be the object of the request processing.
>>>
>>>In OverDrive/Nexus, we do find having interceptors that surround each
>>>request useful. It's not hard to define "pre" and "post" chains, and
>>>then at runtime create a third chain to execute them all.
>>>
>>>public void ExecuteView (IRequestContext context)
>>>{
>>>IRequestCommand command = VerifyRequest (context);
>>>if (context.IsNominal)
>>>{
>>>IChain chain = new Chain ();
>>>if (_PreOp!=null) chain.AddCommand (_PreOp);
>>>chain.AddCommand (command);
>>>if (_PostOp!=null) chain.AddCommand (_PostOp);
>>>try
>>>{
>>>chain.Execute (context);
>>>}
>>>catch (Exception e)
>>>{
>>>context.Fault = e;
>>>}
>>>}
>>>}
>>>
>>>
>>
>>http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/overdrive/Nexus/Extras/Spring/Catalog.cs?view=markup
>>
>>>The PreOp and PostOp chains are defined in the configuration, along
>>>with everything else.
>>>
>>>But, we're not trying to solve the problems of navigational workflows,
>>>only the problem of processing business use cases and interacting with
>>>a presentation layer
>>>
>>>-Ted.,
>>>
>>>---------------------------------------------------------------------
>>>To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
>>>For additional commands, e-mail: dev-help@struts.apache.org
>>>
>>
>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
>>For additional commands, e-mail: dev-help@struts.apache.org
>>
>>
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Craig McClanahan <cr...@gmail.com>.
On 9/1/05, Don Brown <mr...@twdata.org> wrote:
Therefore, my point is an interceptor chain is better suited to a scalable,
> linear process flow, while chain is better for decision points. And
> neither,
> I'd argue, is well suited for a robust, configurable workflow, and this
> surely
> we can agree we are seeing with commons-chain in Struts Classic.
I generally agree with this, and the other points Don has made in this
thread ... and would suggest (sorry Don :-) that the same issue happens with
continuations based architectures like Cocoon Webflow and Struts Flow. None
of these approaches seem to deal with conditional branches in workflows very
well.
This is one of the reasons that I was initially enamored with Spring
WebFlow's approach, which defines the processing logic as a series of
states, linked by transitions. States can be action states (like calling
Action.execute() in a Struts app) or view states (display a page, receive
the subsequent form submit. All states return an outcome that can be used to
drive the transition, so you can do branches very easily. Or, you can glue
together any number of action states in sequence to get the fine grained
sequential functionality that a chain provides.
In Shale, this idea is encapsulated as a "dialog", which leverages the fact
that JSF action methods already returned a String outcome (so that it fit
naturally into the state transition model) -- I just added the idea of an
action state represented as an expression that called some arbitrary method
that also returned a String. This lets you do things like representing an
entire workflow in an easy to understand configuration (or, equivalently, in
a UML state diagram):
<!-- Log On / Create Profile Dialog -->
<dialog name="Log On"
start="Check Cookie">
<action name="Check Cookie"
method="#{profile$logon.check}">
<transition outcome="authenticated"
target="Exit"/>
<transition outcome="unauthenticated"
target="Logon Form"/>
</action>
<view name="Logon Form"
viewId="/profile/logon.jsp">
<transition outcome="authenticated"
target="Exit"/>
<transition outcome="create"
target="Create Profile"/>
</view>
<subdialog name="Create Profile"
dialogName="Edit Profile">
<transition outcome="success"
target="Exit"/>
</subdialog>
<end name="Exit"
viewId="/usecases.jsp"/>
</dialog>
Although the dialog facility is primary focused around multi-request
workflows, you can leverage the same concepts for fine grained flows within
a particular request.
Craig
Don
>
> BTW, I'm really enjoying this discussion and have missed these on this
> list.
>
> Ted Husted wrote:
> > On 9/1/05, Don Brown <mr...@twdata.org> wrote:
> >
> >>In that case, I find interceptors more practical, as they allow
> >>you to have code before and after processing that uses method variables.
> With
> >>Chain, you have to use a Filter and even then, there is no way to share
> >>variables between the two blocks of code without instance variables
> which has
> >>its own problems.
> >
> >
> > First, you're doing the work, Don, and so you're welcome to make the
> > decisions :)
> >
> > Though, I don't understand is why you'd want to be restricted to two
> > blocks of code :)
> >
> > With Chain, any number of blocks of code, be they commands or chains,
> > in any combination, can be the object of the request processing.
> >
> > In OverDrive/Nexus, we do find having interceptors that surround each
> > request useful. It's not hard to define "pre" and "post" chains, and
> > then at runtime create a third chain to execute them all.
> >
> > public void ExecuteView (IRequestContext context)
> > {
> > IRequestCommand command = VerifyRequest (context);
> > if (context.IsNominal)
> > {
> > IChain chain = new Chain ();
> > if (_PreOp!=null) chain.AddCommand (_PreOp);
> > chain.AddCommand (command);
> > if (_PostOp!=null) chain.AddCommand (_PostOp);
> > try
> > {
> > chain.Execute (context);
> > }
> > catch (Exception e)
> > {
> > context.Fault = e;
> > }
> > }
> > }
> >
> >
> http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/overdrive/Nexus/Extras/Spring/Catalog.cs?view=markup
> >
> > The PreOp and PostOp chains are defined in the configuration, along
> > with everything else.
> >
> > But, we're not trying to solve the problems of navigational workflows,
> > only the problem of processing business use cases and interacting with
> > a presentation layer
> >
> > -Ted.,
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> > For additional commands, e-mail: dev-help@struts.apache.org
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> For additional commands, e-mail: dev-help@struts.apache.org
>
>
Re: Spring and XWork in Ti
Posted by Don Brown <mr...@twdata.org>.
Perhaps an example would help convey what I'm trying to say:
Take a simple case where you want to processing time and log it to a file. As a
XWork interceptor, it would look like this:
long startTime = System.currentTimeMillis();
String result = invocation.invoke();
long executionTime = System.currentTimeMillis() - startTime;
log.info("Execution time: "+executionTime+" ms");
Here, we define a method variable, startTime, before the rest of the execution,
then need to access it after the execution is done.
If we wanted to write this as a Filter in commons-chain, we couldn't without
making startTime a class level variable, but then the command would no longer be
thread-safe.
Ah, but you might suggest we write that as a chain since a chain has explicit
control over executing its children. But then, we'd have to define the rest of
the commands within that chain and if you have multiple commands like this timer
command, they too would have to be chains:
process-chain
timer-chain
fooCommand
otherAroundCommand
barCommand
....
This obviously has the disadvantage of deep nesting losing some of the
readability of a simple process chain.
Therefore, my point is an interceptor chain is better suited to a scalable,
linear process flow, while chain is better for decision points. And neither,
I'd argue, is well suited for a robust, configurable workflow, and this surely
we can agree we are seeing with commons-chain in Struts Classic.
Don
BTW, I'm really enjoying this discussion and have missed these on this list.
Ted Husted wrote:
> On 9/1/05, Don Brown <mr...@twdata.org> wrote:
>
>>In that case, I find interceptors more practical, as they allow
>>you to have code before and after processing that uses method variables. With
>>Chain, you have to use a Filter and even then, there is no way to share
>>variables between the two blocks of code without instance variables which has
>>its own problems.
>
>
> First, you're doing the work, Don, and so you're welcome to make the
> decisions :)
>
> Though, I don't understand is why you'd want to be restricted to two
> blocks of code :)
>
> With Chain, any number of blocks of code, be they commands or chains,
> in any combination, can be the object of the request processing.
>
> In OverDrive/Nexus, we do find having interceptors that surround each
> request useful. It's not hard to define "pre" and "post" chains, and
> then at runtime create a third chain to execute them all.
>
> public void ExecuteView (IRequestContext context)
> {
> IRequestCommand command = VerifyRequest (context);
> if (context.IsNominal)
> {
> IChain chain = new Chain ();
> if (_PreOp!=null) chain.AddCommand (_PreOp);
> chain.AddCommand (command);
> if (_PostOp!=null) chain.AddCommand (_PostOp);
> try
> {
> chain.Execute (context);
> }
> catch (Exception e)
> {
> context.Fault = e;
> }
> }
> }
>
> http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/overdrive/Nexus/Extras/Spring/Catalog.cs?view=markup
>
> The PreOp and PostOp chains are defined in the configuration, along
> with everything else.
>
> But, we're not trying to solve the problems of navigational workflows,
> only the problem of processing business use cases and interacting with
> a presentation layer
>
> -Ted.,
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> For additional commands, e-mail: dev-help@struts.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Ted Husted <te...@gmail.com>.
On 9/1/05, Don Brown <mr...@twdata.org> wrote:
>In that case, I find interceptors more practical, as they allow
> you to have code before and after processing that uses method variables. With
> Chain, you have to use a Filter and even then, there is no way to share
> variables between the two blocks of code without instance variables which has
> its own problems.
First, you're doing the work, Don, and so you're welcome to make the
decisions :)
Though, I don't understand is why you'd want to be restricted to two
blocks of code :)
With Chain, any number of blocks of code, be they commands or chains,
in any combination, can be the object of the request processing.
In OverDrive/Nexus, we do find having interceptors that surround each
request useful. It's not hard to define "pre" and "post" chains, and
then at runtime create a third chain to execute them all.
public void ExecuteView (IRequestContext context)
{
IRequestCommand command = VerifyRequest (context);
if (context.IsNominal)
{
IChain chain = new Chain ();
if (_PreOp!=null) chain.AddCommand (_PreOp);
chain.AddCommand (command);
if (_PostOp!=null) chain.AddCommand (_PostOp);
try
{
chain.Execute (context);
}
catch (Exception e)
{
context.Fault = e;
}
}
}
http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/overdrive/Nexus/Extras/Spring/Catalog.cs?view=markup
The PreOp and PostOp chains are defined in the configuration, along
with everything else.
But, we're not trying to solve the problems of navigational workflows,
only the problem of processing business use cases and interacting with
a presentation layer
-Ted.,
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Don Brown <mr...@twdata.org>.
Joe Germuska wrote:
>> Just as we discovered Chain commands were difficult to use for Struts
>> users (all the casting for one), Ti users will generally write
>> interceptors and not chain commands. Interceptors are more natural,
>> support around operations better due to easier use local variables,
>> and provider easier access to the Action they are intercepting with no
>> casting.
>
>
> I'm just wondering when this discovery was made. I don't recall seeing
> a lot of discussion about it. I don't know enough about WebWork
> interceptors to argue whether they are easier or not, although it seems
> like if you really want to implement "around" style programming, they
> would fit better, since the model with which Struts executes per-mapping
> commands doesn't really give you anything to wrap around. I guess you
> can always make a chain with filters; I can't think of a time I ever
> wanted to apply a solution like that, so it's pretty abstract to me. I
> just don't remember there being much discussion about whether commands
> were easy or hard.
I'm referring to more to how chain worked before we added our own ActionContext,
and even then, I personally find its "return true or false" unintuitive for
process flow. In that case, I find interceptors more practical, as they allow
you to have code before and after processing that uses method variables. With
Chain, you have to use a Filter and even then, there is no way to share
variables between the two blocks of code without instance variables which has
its own problems.
That is not to say I don't like chain, but I think it is better suited for
"chain of responsibility" needs rather than process flow, and when it comes to
the end user, we should make things as easy and intuitive as possible.
Interceptors, following the pattern of Servlet filters, does that, IMO.
XWork and WebWork have a ton of examples of interesting uses of interceptors,
but one in particular is their WorkflowInterceptor, which brings Struts
Classic-style workflow (populate, validate, if fails, goto input) to Ti/Webwork.
What is interesting is this is optional and can be replaced if a different
workflow suites you better in a very straightforward way (see xwork.xml
interceptor defs which will be annotations in Ti).
>
>> In Ti, while we do use chain for general request processing, where I
>> think it really shines is decision points, something the CoR is built
>> to solve. A good example is the chain that creates a form bean. A
>> chain is called, and the first command that sees it can create it,
>> does, then returns "true" as the responsibility has been assumed. So
>> in summary, Ti developers will work with chains and some interceptors,
>> while the average Ti application will only need to know interceptors.
>
>
> Ti depends on commons-chain 1.0. The LookupCommand in that version of
> commons-chain treats a "true" return value from any called chain as a
> signal to abort the entire chain processing. Did Ti reimplement the
> idea that some commands would ignore the return value from a
> looked-up-chain, as has since been added to the unreleased SVN head of
> commons-chain? Or has that just not been noticed yet?
The key here is Ti doesn't have "one chain to rule them all", but periodically
uses special purposes chains. This form chain I'm referring to is not directly
connected to the main processing chain at all, but is initiated by another
component. These special purpose chains I think matches the original intent of
commons-chain better than as a limited workflow language, again, in my humble
opinion :).
Don
>
> Joe
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Joe Germuska <Jo...@Germuska.com>.
>Just as we discovered Chain commands were difficult to use for
>Struts users (all the casting for one), Ti users will generally
>write interceptors and not chain commands. Interceptors are more
>natural, support around operations better due to easier use local
>variables, and provider easier access to the Action they are
>intercepting with no casting.
I'm just wondering when this discovery was made. I don't recall
seeing a lot of discussion about it. I don't know enough about
WebWork interceptors to argue whether they are easier or not,
although it seems like if you really want to implement "around" style
programming, they would fit better, since the model with which Struts
executes per-mapping commands doesn't really give you anything to
wrap around. I guess you can always make a chain with filters; I
can't think of a time I ever wanted to apply a solution like that, so
it's pretty abstract to me. I just don't remember there being much
discussion about whether commands were easy or hard.
>In Ti, while we do use chain for general request processing, where I
>think it really shines is decision points, something the CoR is
>built to solve. A good example is the chain that creates a form
>bean. A chain is called, and the first command that sees it can
>create it, does, then returns "true" as the responsibility has been
>assumed. So in summary, Ti developers will work with chains and
>some interceptors, while the average Ti application will only need
>to know interceptors.
Ti depends on commons-chain 1.0. The LookupCommand in that version
of commons-chain treats a "true" return value from any called chain
as a signal to abort the entire chain processing. Did Ti reimplement
the idea that some commands would ignore the return value from a
looked-up-chain, as has since been added to the unreleased SVN head
of commons-chain? Or has that just not been noticed yet?
Joe
--
Joe Germuska
Joe@Germuska.com
http://blog.germuska.com
"Narrow minds are weapons made for mass destruction" -The Ex
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Don Brown <mr...@twdata.org>.
This is a good question that deserves a wiki writeup as I'm guessing
I'll get asked it a lot :)
While chain and xwork interceptors do overlap some in theory, they
overlap very little in practice. Chain is a general purpose, chain of
responsibility pattern that is better suited, IMO, for general request
processing, initialization, decision points, etc. XWork interceptors
are more like Servlet Filters, and are specificly designed to intercept
an action execution.
Just as we discovered Chain commands were difficult to use for Struts
users (all the casting for one), Ti users will generally write
interceptors and not chain commands. Interceptors are more natural,
support around operations better due to easier use local variables, and
provider easier access to the Action they are intercepting with no casting.
In Ti, while we do use chain for general request processing, where I
think it really shines is decision points, something the CoR is built to
solve. A good example is the chain that creates a form bean. A chain
is called, and the first command that sees it can create it, does, then
returns "true" as the responsibility has been assumed. So in summary,
Ti developers will work with chains and some interceptors, while the
average Ti application will only need to know interceptors.
Hope that helps,
Don
Ted Husted wrote:
> On 8/31/05, Don Brown <mr...@twdata.org> wrote:
>
>>I should really list this out on the wiki site. The short of it is XWork gives us an Action framework, interceptor
>>chains, expression language support, l18n, validation, and the value stack.
>
>
> Do we need both interceptor chains and CoR chains?
>
> Would it be possible to code a Struts Request Processor using an
> XWorks interceptor chain?
>
> -Ted.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> For additional commands, e-mail: dev-help@struts.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org
Re: Spring and XWork in Ti
Posted by Ted Husted <te...@gmail.com>.
On 8/31/05, Don Brown <mr...@twdata.org> wrote:
> I should really list this out on the wiki site. The short of it is XWork gives us an Action framework, interceptor
> chains, expression language support, l18n, validation, and the value stack.
Do we need both interceptor chains and CoR chains?
Would it be possible to code a Struts Request Processor using an
XWorks interceptor chain?
-Ted.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org