You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Michael Jouravlev <jm...@gmail.com> on 2005/07/06 23:03:03 UTC

Struts MVC design (was:: help with a newbie topic-prepopulating a form)

On 7/6/05, Adam Hardy <ah...@cyberspaceroad.com> wrote:
> I pity the poor noob who asked the original question! Little did he
> suspect that he would spark off a dialog on advanced MVC design.
> 
> This debate has come up before and for me, it is one of the weak points
> of struts - I remember a couple of years back someone on the list
> complaining that Struts wasn't 'OO' because the data and logic were
> seperated into Actions and ActionForms. I remember Craig M. almost
> agreeing.

Looking at JSF backing beans, he ultimately agreed.

> Now there is talk of Struts in the future containing ActionCommands
> which can be substituted in place of Actions, and strung together in a
> chain, and presumably can perform View-Controller logic.

My previous design used chaining of different actions, like to chain
from 'create' to 'edit' to implement 'add new' operation. But now I
use a single action class with dispatch-style handlers and redirecting
to itself for rendering. Technically, it is not even chaining, because
I do not use in-server forwarding, I use redirection.

On 7/6/05, Rick Reumann <st...@reumann.net> wrote:
> Michael Jouravlev wrote the following on 7/6/2005 12:26 PM:
> 
> > So, you use action forms both for input and output. This is great.
> > Change the scope to "session", throw in some methods, and you get
> > yourself a backing bean. This is what it should be.
> 
> Well, not really. I should be able to use a POJO/ValueObject not tied to
> Struts packages. A true backing bean could be used on the backend and
> front interchangeably. Sure, if I wanted to tie my entire backend to
> Struts I could be passing around the ActionForm everywhere, but I don't
> really like doing that (the whole seperation thing again:).

Right, I would like to use a POJO/VO/BO outside Struts too. Let us
establish a use case: to use a BO in input/output mode, that is to
[semi-]automatically populate it from request, and to have it provide
values for JSP page. So, I see two choices for this use case:

(A) Define getters and setters for all properties of BO right in the
form bean. This way all form bean properties are defined as strings.
This helps to retain values from request, even if they are incorrect,
because no conversion to native type is made. The values can be
validated with standard validate method, and I don't have to worry
about consistency of a real BO.

I would need to define setters/getters again, and to copy values
from/to BO. On the other hand, I would need to copy those values only
at init and then at store. If a user makes several submit attempts, I
copy nothing to BO.

(B) Set up a BO as a property of the form bean. Struts will access it
as nested property and will be able to set and read its internal
fields. I will need to use qualifiers to access properties of a BO
from JSP page. In this case BO should accept string values, and should
have built-in validation and conversion mechanisms.

In this case I have a pretty isolated BO, which can handle raw string
data, and can validate it. I think this way is better for systems
where Struts is not the only front end, and there is a lot business
logic and business validation on the backend.

> I often use the same
> ActionForm in many diffrent cicumstances. I wouldn't want it always
> being populated (the "add" was just one example) so you'd need a
> mechanism to decide when and when not to call the populate and, not only
> that, but what gets populated might need to change based on what the
> ActionForm is being used for. For example, you might have a generic
> UserForm (name and ID - for simplicity)- this form might sometimes be
> used for dealing with Accounting users or sometimes HR Users. In order
> to resuse this form in many different circumstances you'd have to have a
> bunch of conditional logic in your ActionForm. I find it cleaner to
> avoid that logic. I find it cleaner to bind that userForm to different
> ActionMappings and thus the resulting Action takes care of knowing what
> to do, vs putting all the responsibility on the ActionForm knowing how
> to populate itself.

A-ha. You keep your action form clean and "multipurpose" so you can
reuse it. But your action class performs business logic specific for
every use case, so you cannot reuse it. If you were to create a
library, you would have to provide base action forms, which would be
reused or subclassed, but a user of your library would have to define
a new action class anyway.

Now, let's look at it from another side. The action class is
multipurpose, it can be either subclassed or in many cases used as is.
This is a clean benefit for a user of a library. The action class
provides the event contract, while the action form does the dirty
work. The library does not have a clue about real data in every
different case, but in might have some knowledge about the protocol,
and about lifecycle.

So, the library provides an interface which action form implements.
This way it behaves according to protocol, but has the concrete logic
for a particular business object. Also, using action forms
implementing certain interface does not preclude from subclassing
certain useful action form like ValidateForm.

Stateful action form contains all needed data, so methods can easily
access this data without needing to have a reference to a form and to
cast it to proper type every time.

Did I convince you that having business logic in an action form is
better? Action class provides external I/O contract and manages
messages and navigation, while action form performs operations on
business data, *where it is actually stored* .

> > The simplification of this approach is using of dispatch action and
> > redirecting from it to itself. Commands like 'create', 'edit', 'view'
> > are dispatched to handlers, which load or create an object, then
> > handlers redirect to the same action, which displays whatever is in
> > the form. See details here:
> > http://struts.sourceforge.net/strutsdialogs/crudaction.html
> > All CRUD operations are neatly provided by one class, but of course it
> > should be backed by an action form, which does the dirty work ;)
> 
> Guess I'm too old skool, I like the dirty work called from my Action
> dispatch (CRUD) methods.

See above. Maybe you give it a second thought ;)

Michael.

--
Dialogs for Struts
http://struts.sourceforge.net/strutsdialogs

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Struts MVC design

Posted by Craig McClanahan <cr...@gmail.com>.
On 7/6/05, Michael Jouravlev <jm...@gmail.com> wrote:
> On 7/6/05, Craig McClanahan <cr...@gmail.com> wrote:
> > On 7/6/05, Adam Hardy <ah...@cyberspaceroad.com> wrote:
> > >
> > > Now there is talk of Struts in the future containing ActionCommands
> > > which can be substituted in place of Actions, and strung together in a
> > > chain, and presumably can perform View-Controller logic.
> > >
> >
> > If you look at Shale (with its support for both ViewController and
> > Dialog -- which, among other things, lets you intersperse action
> > states and view states to your heart's desire), you'll find that the
> > future is now :-)
> >
> >   http://struts.apache.org/shale/
> >
> > Craig
> 
> Moved to the new thread.
> 
> From http://struts.apache.org/shale/features.html#view
> 
> "Each backing bean that implements ViewController will support a
> boolean property postback, which will be set to true if this view is
> the one that is processing a form submit previously rendered by the
> same page, or false if this view was newly navigated to."
> 
> * How is this different from ASP.NET?

The ViewController part of Shale is indeed very similar to the way
that ASP.NET implements the View Helper design pattern.  From a
usability perspective, especially for developers not as well versed in
object oriented programming concepts, Microsoft got this right --
which was one of the motivations for JSF making the same style easy to
accomplish in Java.  When you are focused on a particular page, it is
very convenient to think of everything that happens related to that
page being a response to a particular event -- with all the events for
a particular page conveniently represented as public methods on a
single backing bean (code behind file in ASP.NET terminology).  The
prerender() method, as well, performs exactly the same function as the
Controller interface in Tiles -- it provides a perfect place to
acquire resources that are *only* required if you are the page that is
going to be rendered.

Struts 1.x supports exactly the same paradigm; it's just not as pretty
-- a setup action that preceeds the rendered view action. 
ViewController doesn't require you to do that extra step (or try to
deal with the problematic action chaining issues that plague Struts
1.x, when you submit to the processing action for the previously
rendered form, then need to navigate to the setup action for the form
about to be rendered).

And, if you go on and also use the Dialog feature of Shale, you can
have as many different action states (each represented by a method
call, expressed as a method binding expression so the business logic
classes need have no knowledge of JSF or Shale) as you want in between
your views.  So, if you like the way a chain of responsibility pattern
(like Commons Chain) lets you decompose business processes into fine
grained reusable chunks, you can do that too.

> * Does not this make Shale page-based instead of front-controller
> based? MS recognized lack of front controller support in ASP.NET 1.0
> and will provide it to the second version.

No, it makes the *ViewController* part of Shale page based, as it should be :-).

The rest of Shale (in particular the controlling filter where you can
plug in anything that is supposed to happen once per request, like an
authentication filter) is still a front controller.  You can impose
whatever overall processing you want on each request, simply by
composing the Commons Chain command that the filter applies to each
request.

Besides the biggest difference (from Struts) of being JSF based, this
architectural principle is the second major difference in Shale, and
it results from the most important lesson I've learned by watching how
people use (and misuse) Struts -- the controller framework should
consist of fine grained components that can be combined or customized
as necessary to meet particular application requirements.  If a
particular application needs, say, authentication filtering, then plug
it in.  If that app also needs logging, or tracing, plug that in too
(no having to worry about subclassing RequestProcessor and then
running into Java's single inheritance limitation.

At the same time, it is up to the application architect if they want
to build up the specialized processing needed for an individual
request by composing with reusable logic blocks.  You can do this
easily with Shale, either by calling common reusable code chunks from
methods like prerender() and destroy() when using ViewController, or
by composing the action states in between your views when using
Dialog.  The front controller managing the entire application need not
be involved in figuring out what specialized resources the particular
processing path for a given request will need -- although you could
even do that in the application level filter, if you really wanted to.
 Your choice.

What's interesting about the current discussion is that things like
DispatchAction and LookupAction, as well as the idea of action
commands, are all an attempt to retrofit exactly the same concept of
fine grained management of individual interactions onto the monolithic
controller of Struts 1.x.  As some have observed, the two approaches
don't necessarily fit together very well -- although you can certainly
do it with some bending and twisting.

But the architectural model of an application that Shale presents to
the developer, once you learn it, is *much* simpler to program to, as
well as being easier to configure.

Craig

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Struts MVC design

Posted by Dakota Jack <da...@gmail.com>.
Shale may purloin the name "Struts" but their is no Struts to Shale at
all.  Mark G. may or may not harm Struts (I don't think people are so
stupid as to let that influence their career decisions actually) but
Shale will kill Struts utterly, if Shale, which is very unlikely,
should be chosen to supercede Struts.

On 7/6/05, Michael Jouravlev <jm...@gmail.com> wrote:
> On 7/6/05, Craig McClanahan <cr...@gmail.com> wrote:
> > On 7/6/05, Adam Hardy <ah...@cyberspaceroad.com> wrote:
> > >
> > > Now there is talk of Struts in the future containing ActionCommands
> > > which can be substituted in place of Actions, and strung together in a
> > > chain, and presumably can perform View-Controller logic.
> > >
> >
> > If you look at Shale (with its support for both ViewController and
> > Dialog -- which, among other things, lets you intersperse action
> > states and view states to your heart's desire), you'll find that the
> > future is now :-)
> >
> >   http://struts.apache.org/shale/
> >
> > Craig
> 
> Moved to the new thread.
> 
> From http://struts.apache.org/shale/features.html#view
> 
> "Each backing bean that implements ViewController will support a
> boolean property postback, which will be set to true if this view is
> the one that is processing a form submit previously rendered by the
> same page, or false if this view was newly navigated to."
> 
> * How is this different from ASP.NET?
> * Does not this make Shale page-based instead of front-controller
> based? MS recognized lack of front controller support in ASP.NET 1.0
> and will provide it to the second version.
> 
> Resource-based apps like Struts Classic can return whatever page they
> want from the same location, while page-based apps tie resource
> address to a page, which can lead to unfriendly Back experience. This
> can be worked around, but why if Struts Classic already provides
> better approach?
> 
> Sure, a component should be able to be initialized when needed. It can
> be done easily with initialization parameter.
> 
> Shale Dialogs is based on Spring Webflow, which, when I checked the
> last time, did not support Back button and clean refresh. Hopefully,
> Shale Dialogs behaves more user-friendly.
> 
> Nevertheless, Struts Dialogs has WizardAction, which provides support
> for dialogs and wizards, based on Easy Wizard concept:
> http://today.java.net/pub/a/today/2005/03/15/webwizard1.htm
> http://today.java.net/pub/a/today/2005/03/29/webwizard2.htm
> WizardAction subclasses DialogAction and implements wizard's UI Controller.
> 
> see the demo: http://www.superinterface.com/strutsdialog/wizardaction.do
> Notice, that Refresh works, and that you cannot go back to a previous
> page (unless you use Opera).
> 
> The above is possible with adding of only two action classes to classic Struts.
> 
> Michael
> 
> --
> Struts Dialogs
> http://struts.sourceforge.net/strutsdialogs
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
> 
> 


-- 
"You can lead a horse to water but you cannot make it float on its back."
~Dakota Jack~

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Struts MVC design

Posted by Michael Jouravlev <jm...@gmail.com>.
On 7/6/05, Craig McClanahan <cr...@gmail.com> wrote:
> On 7/6/05, Adam Hardy <ah...@cyberspaceroad.com> wrote:
> >
> > Now there is talk of Struts in the future containing ActionCommands
> > which can be substituted in place of Actions, and strung together in a
> > chain, and presumably can perform View-Controller logic.
> >
> 
> If you look at Shale (with its support for both ViewController and
> Dialog -- which, among other things, lets you intersperse action
> states and view states to your heart's desire), you'll find that the
> future is now :-)
> 
>   http://struts.apache.org/shale/
> 
> Craig

Moved to the new thread. 

>From http://struts.apache.org/shale/features.html#view 

"Each backing bean that implements ViewController will support a
boolean property postback, which will be set to true if this view is
the one that is processing a form submit previously rendered by the
same page, or false if this view was newly navigated to."

* How is this different from ASP.NET?
* Does not this make Shale page-based instead of front-controller
based? MS recognized lack of front controller support in ASP.NET 1.0
and will provide it to the second version.

Resource-based apps like Struts Classic can return whatever page they
want from the same location, while page-based apps tie resource
address to a page, which can lead to unfriendly Back experience. This
can be worked around, but why if Struts Classic already provides
better approach?

Sure, a component should be able to be initialized when needed. It can
be done easily with initialization parameter.

Shale Dialogs is based on Spring Webflow, which, when I checked the
last time, did not support Back button and clean refresh. Hopefully,
Shale Dialogs behaves more user-friendly.

Nevertheless, Struts Dialogs has WizardAction, which provides support
for dialogs and wizards, based on Easy Wizard concept:
http://today.java.net/pub/a/today/2005/03/15/webwizard1.htm
http://today.java.net/pub/a/today/2005/03/29/webwizard2.htm
WizardAction subclasses DialogAction and implements wizard's UI Controller.

see the demo: http://www.superinterface.com/strutsdialog/wizardaction.do
Notice, that Refresh works, and that you cannot go back to a previous
page (unless you use Opera).

The above is possible with adding of only two action classes to classic Struts.

Michael

--
Struts Dialogs
http://struts.sourceforge.net/strutsdialogs

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Struts MVC design

Posted by Michael Jouravlev <jm...@gmail.com>.
On 7/6/05, Rick Reumann <st...@reumann.net> wrote:
> Michael Jouravlev wrote the following on 7/6/2005 5:03 PM:
> 
> > The action class
> > provides the event contract, while the action form does the dirty
> > work.
> 
> Well in this case the struts-config file would provide the contract and
> you could simply use one ForwardAction for everything. You've
> substituted numerous Actions (or DispatchAction methods) and replaced
> them with either A) numerous ActionForms (probably sharing the same
> field names or B) complext logic in single ActionForms to decide on what
> 'business logic' to do.

I cannot use ForwardAction for everything because I need to dispatch
the button click to a handler. DispatchAction (its subclass) provides
dispatching of events. My ActionForms do not have complex logic, they
have simple methods like crudCreate or crudLoad or crudDelete. These
methods are called from action class. Action class itself can be
reused in different apps or in the same app, because it is stateless.
ActionForm is stateful (has session scope), has specific business code
and properties for every particular business object. Generally,
actionforms are not shared.

> > Did I convince you that having business logic in an action form is
> > better? Action class provides external I/O contract and manages
> > messages and navigation, while action form performs operations on
> > business data, *where it is actually stored* .
> 
> No you haven't convinced me at all:) I still see no practical benefit to
> flipping struts inside out like this. 

I just explained where benefit is: with your approach you reuse forms,
but define specific action classes. I suggest to reuse action classes,
but to define specific forms. Is not it the same thing? I don't think
so, because action classes can define different contracts, for example
for yes/no dialog, or for next/back/cancel wizard of for
create/edit/view/delete form. These action classes can be reused.
Action form works with specific data, so it is natural, that it should
not be reused.

I will think of better reasons ;)

> (I don't think the method names "reset" and "validate" would be chosen as
> method names in an ActionForm if they were designed for doing all kinds
> of business logic in them.

Oops, I see misunderstanding here. I did not say that business logic
should be implemented in reset and validate. Not at all. There are
intefaces, which are implemented by action forms. I hope you will find
time to look at my stuff, because it is explained there and in the
source code.

> I think if you go this route, you should say it's a different version of
> Struts.. maybe StrutsWorks or something:)

You got me: I was thinking of spawning off Struts to something else,
but I would like first to convince its power users and committers,
that the change I am suggesting is good. If this does not work, I may
consider borrowing Struts core, add my stuff to it and call it
StrutsWorks ;) I figured, that to do that I need at least 30% of my
own code, and now I do not have critical mass yet. Another issue is
users, who would learn new controller framework, when there are
exciting alternatives like Wicket?

> Under the scenario you've
> proposed I don't see what the point of using any Actions would be? Why
> not just use the one default FowardAction and do everything in the
> ActionForm?

Right, in many cases I would prefer action form to do the dispatching
and forwarding to a view. But in other cases I would prefer to reuse
standard action class, and to define business methods in a form bean.
So, I don't want to *change* everything, I want to *add* new options.

Michael.

--
Dialogs for Struts
http://struts.sourceforge.net/strutsdialogs

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Struts MVC design

Posted by Rick Reumann <st...@reumann.net>.
Michael Jouravlev wrote the following on 7/6/2005 5:03 PM:

> The action class
> provides the event contract, while the action form does the dirty
> work.  

Well in this case the struts-config file would provide the contract and 
you could simply use one ForwardAction for everything. You've 
substituted numerous Actions (or DispatchAction methods) and replaced 
them with either A) numerous ActionForms (probably sharing the same 
field names or B) complext logic in single ActionForms to decide on what 
'business logic' to do.

> Did I convince you that having business logic in an action form is
> better? Action class provides external I/O contract and manages
> messages and navigation, while action form performs operations on
> business data, *where it is actually stored* .

No you haven't convinced me at all:) I still see no practical benefit to 
flipping struts inside out like this. Sure it'll work, and I'm not even 
saying (without a lot more thought:) that it's "bad," but it certainly 
totally turns around the way the framework was designed to work. (I 
don't think the method names "reset" and "validate" would be chosen as 
method names in an ActionForm if they were designed for doing all kinds 
of business logic in them.

I think if you go this route, you should say it's a different version of 
Struts.. maybe StrutsWorks or something:) Under the scenario you've 
proposed I don't see what the point of using any Actions would be? Why 
not just use the one default FowardAction and do everything in the 
ActionForm?

(In case someone is popping into this thread late, I'm certainly not 
advocating this:)

-- 
Rick

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org