You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by Thomas Burleson <Th...@Calmwaters.com> on 2001/08/07 06:59:14 UTC

Help with ActionForms and Actions... (Craig or Ted or anyone)

I have a serious design concern that I need feedback on. - Craig, Ted, ...
:-))
Perhaps, my concern is just a misunderstanding, but HELP!

Okay! Here is the issue (actually 2):

<Current Understanding>
Each web page/form has an associated actionform(bean) and action(request
handler).
The Struts engine instantiates and fills the bean based on the incoming
request parameters.
Then the bean is optionally give the chance to validate the data. Then the
bean is delivered to the action(handler) for processing.
An action forward is generated and the new jsp/html is dispatched.
The JSP, in turn, searches for the bean in the request scope. If not found,
a bean is instantiated and must set its own values.

<Design Understanding>
Incoming requests are processed with a Model2 approach... View submits data
to Controller which "interacts" with Model and then dispatchs to View. But
the Struts architecture seems to then have the View interact with the Model
also. If the JSP has to create an actionform and the actionform knows how to
interact with the business layer, this seems to TOTALLY violate the concept
of MVC.
Because now, not only does the action "know" about the business layer, but
so does the actionform.

And...
1) What if the default values of the actionForm required complicated logic
to determine those values. This means that the use of actionForms (by a JSP)
to directly set/load those values has introduced tight coupling to the
business layer or model data.

So...Should the actionform just be considered a valueObject... a dumb
container? It would be used
to hold values for an incoming request and also to hold values for a
outgoing request. This would mean that the action would be required to
process outgoings also; e.g. doOnShow() and doOnSubmit().
This "new" step would allow only the actions to contain ALL knowledge of the
business layer. AND when the JSP used the bean (searching the request
scope), the bean will have already been prepared by the action/handler and
saved to the scope before dispatching occurs.

Also (2),
A problem occurs if my displayed web page is actually a template composed of
multiple JSPs... where each included JSP can be considered a "component".
How would Struts deal with these? And what if a "component" included OTHER
components!?
	1) How are the actions called. And in what order?
	2) How could each "component" define separate _targets (if needed)?

I can elaborate of these questions if needed. But I really do need some
insight into these disturbing questions.



-----Original Message-----
From: Ted Husted [mailto:husted@apache.org]
Sent: Monday, August 06, 2001 1:28 PM
To: struts-dev@jakarta.apache.org
Subject: Re: Type of form-beans


Personally, I would make the Address bean a second object, at least
temporarily. Once a validated Address had been entered, I would merge it
with the product bean in the session, and proceed from there.

-Ted.

Ronald Bakker wrote:
>
> Hello everybody,
>
> First, I want to apologise for the fact that my previous message was
> posted multiple times in this mailing list. Our sendmail log sent it
> only once, so I do't really understand what went wrong.
>
> Back to the issue. Consider the following case we're dealing with in our
> application:
>
> We're working on an e-commerce application with which people can order
> different kind of products. Ordering a product consists of two parts:
> first they have to fill in a product specific form to get a price quote
> for the requested product. Then, if they accept the quote, they have to
> fill in address information for delivery. Filling in address information
> uses the same form for all different products.
>
> What we want to do is the following:
> For each product, we define an action in struts-config.xml. Each action
> uses an own, product specific form, say productAFrom, productBForm
> etcetera. Each of these forms is an extension of an abstract class
> productForm.
> For the address information part, we want to define one additional
> action in struts-config.xml, which uses the abstract productForm as
> form-bean.
>
> Since filling in the address information form always follows the product
> ordering form, we know that the user always has a productForm stored as
> attribute in his session.
>
> I do realize that this mechanism gives some more responsibility to the
> developer, in that he has to be careful using an abstract class name as
> the type of a form bean, but I don't know any better alternatives yet.
> Maybe using the same conventions as jsp:usebean, create a new instance
> of an action form only if a 'class' attribute is present, if just a
> 'type' attribute is present only try to recycle existing instances.
>
> Any suggestions?
>
> Ronald Bakker
> Virgil PM&C
>
> "Craig R. McClanahan" wrote:
> >
> > On Mon, 6 Aug 2001, Ronald Bakker wrote:
> >
> > > Hi everybody,
> > >
> > > In Struts, form-beans can be described by 'name' and 'type'. Looking
at
> > > method 'processActionForm' in ActionServlet, I conclude that roughly
the
> > > following is happening (correct me if I'm wrong):
> > >
> > > When trying to find a form-bean from a mapping, Struts tries to find
an
> > > attribute with the given 'name' in the scope that is defined for this
> > > mapping, if the class name of the found attribute is equal to 'type'
it
> > > will reuse this found attribute. Otherwise a new form-bean instance of
> > > class 'type' is created and placed in scope.
> > >
> >
> > That's a correct understanding.
> >
> > > To my opinion, one fallback of this implementation is that you are
> > > forced to use the implementing class name of the form-bean you intend
to
> > > use, you are not able to use an interface or abstract class name. Is
> > > there any chance Struts is going to use a more flexible way of
> > > retrieving form-beans from a mapping? I would like Struts to use the
> > > same mechanism as jsp:useBean, where you are more flexible in using
> > > beans with  either 'type' or 'class'.
> > >
> >
> > Remember that <jsp:useBean> has a restriction -- if the bean is not
> > already there in the correct scope, you *must* have specified the actual
> > class name so that <jsp:useBean> can instantiate it.  Struts will often
> > (and, if you're using request scope form beans, *always*) need this
> > information anyway, for the same reason.
> >
> > > Right now, we replaced this part of processActionForm with an own
> > > mechanism of reusing form-beans:
> > >
> > > /**
> > >  * Original Struts code:
> > >  */
> > >
> > > // Can we recycle the existing form bean instance?
> > > if ((instance != null) &&
> > >   className.equals(instance.getClass().getName())) {
> > >   if (debug >= 1) {
> > >     log(" Recycling existing ActionForm bean instance of class '"
> > >         + className + "'");
> > >   }
> > >
> > >   return (instance);
> > > }
> > >
> > > /**
> > >  * Replaced by our code:
> > >  */
> > >
> > > // Can we recycle the existing form bean instance?
> > > try {
> > >
> > >   if ((instance != null) &&
> > > Class.forName(className).isInstance(instance)) {
> > >     if (debug >= 1) {
> > >       log(" Recycling existing ActionForm bean instance of class '"
> > >           + className + "'");
> > >     }
> > >     return (instance);
> > >   }
> > > }
> > > catch (ClassNotFoundException ce) {
> > >
> > >   if (debug >= 1) {
> > >     log(" Class not found: '" + className + "'");
> > >   }
> > >   return null;
> > > }
> > >
> >
> > I can see what you're after, but won't this only work in the case of
> > session beans that were previously created by an Action?  For anyone
else,
> > you'll just get an instantiation error.
> >
> > Note to self -- if we change the logic here, a similar change will be
> > needed inside the <html:form> tag, which can also create the form bean
> > dynamically if needed.
> >
> > > Ronald Bakker
> > > Virgil PM&C
> > >
> >
> > Craig


Re: Help with ActionForms and Actions... (Craig or Ted or anyone)

Posted by Ted Husted <hu...@apache.org>.
> This "new" step would allow only the actions to contain ALL knowledge of the
> business layer. AND when the JSP used the bean (searching the request
> scope), the bean will have already been prepared by the action/handler and
> saved to the scope before dispatching occurs.

This should be considered the default behavior. The html:form tag only
instantiates an ActionForm object if and only if one does not already
exist. If a developer is following strict MVC, then all of the pages
will be under WEB-INF, where they cannot be directly accessed, and
control must pass through the Action first. 

In the usual scheme, the ActionController will create the bean when the
ActionMapping is fired, and then hand it to the Action's perform()
method. The Action then forwards the ActionForm to the JSP. At this
point, the ActionForm is instantiated, and not created by the JSP. 

In an Insert|Update workflow, there are usually three ActionMappings,
one for "add", to return an empty ActionForm, one for "edit", to return
a populated ActionForm, and one for "store" to either insert or update
the ActionForm properties into the model. Usually, all three of these
are mapped to the same Action. A good way to tell them apart is to use
the parameter property with your mapping. The Action can the call
mapping.getParameter() and switch to the appropriate "sub-Action".

Now that you mention it (below), I suppose ActionForms are ValueObjects.
They are meant as an adapter between HTTP and the rest of your
application. Usually VOs discussed as adapters between the model and the
rest of your appplication, but it is really the same thing, just in the
other direction. 

So, yes they are HTTP ValueObjects, as opposed to Model ValueObjects. In
most applications, the Model ValueObjects will want to access native
types, and should be their own object, and not bound to Struts. The
Action then becomes an Integration Layer between the HTTP ValueObjects
(in the Presentation Layer) and the Model ValueObjects (in the Business
Layer). 

(2)

HTTP requires that a form, or any other request, be submitted to exactly
one URI. The ActionPath specified by the html:form determines the
*default* ActionForm beans for the controls it encloses. The individual
controls can also specify a different ActionForm bean if they like.
These properties will end up in the request, along with everything else,
and the Action can grab them "the old fashioned way", with
request.getParameter(). (Not to be confused with mapping.getParameter()
;-)

-Ted.

While these are certainly design issues, they are not development issues
per se, and so I'm copying this back to the User list too. I'd suggest
any replies be made to the thread on the User list.


Thomas Burleson wrote:
> 
> I have a serious design concern that I need feedback on. - Craig, Ted, ...
> :-))
> Perhaps, my concern is just a misunderstanding, but HELP!
> 
> Okay! Here is the issue (actually 2):
> 
> <Current Understanding>
> Each web page/form has an associated actionform(bean) and action(request
> handler).
> The Struts engine instantiates and fills the bean based on the incoming
> request parameters.
> Then the bean is optionally give the chance to validate the data. Then the
> bean is delivered to the action(handler) for processing.
> An action forward is generated and the new jsp/html is dispatched.
> The JSP, in turn, searches for the bean in the request scope. If not found,
> a bean is instantiated and must set its own values.
> 
> <Design Understanding>
> Incoming requests are processed with a Model2 approach... View submits data
> to Controller which "interacts" with Model and then dispatchs to View. But
> the Struts architecture seems to then have the View interact with the Model
> also. If the JSP has to create an actionform and the actionform knows how to
> interact with the business layer, this seems to TOTALLY violate the concept
> of MVC.
> Because now, not only does the action "know" about the business layer, but
> so does the actionform.
> 
> And...
> 1) What if the default values of the actionForm required complicated logic
> to determine those values. This means that the use of actionForms (by a JSP)
> to directly set/load those values has introduced tight coupling to the
> business layer or model data.
> 
> So...Should the actionform just be considered a valueObject... a dumb
> container? It would be used
> to hold values for an incoming request and also to hold values for a
> outgoing request. This would mean that the action would be required to
> process outgoings also; e.g. doOnShow() and doOnSubmit().
> This "new" step would allow only the actions to contain ALL knowledge of the
> business layer. AND when the JSP used the bean (searching the request
> scope), the bean will have already been prepared by the action/handler and
> saved to the scope before dispatching occurs.
> 
> Also (2),
> A problem occurs if my displayed web page is actually a template composed of
> multiple JSPs... where each included JSP can be considered a "component".
> How would Struts deal with these? And what if a "component" included OTHER
> components!?
>         1) How are the actions called. And in what order?
>         2) How could each "component" define separate _targets (if needed)?
> 
> I can elaborate of these questions if needed. But I really do need some
> insight into these disturbing questions.
> 
> -----Original Message-----
> From: Ted Husted [mailto:husted@apache.org]
> Sent: Monday, August 06, 2001 1:28 PM
> To: struts-dev@jakarta.apache.org
> Subject: Re: Type of form-beans
> 
> Personally, I would make the Address bean a second object, at least
> temporarily. Once a validated Address had been entered, I would merge it
> with the product bean in the session, and proceed from there.
> 
> -Ted.
> 
> Ronald Bakker wrote:
> >
> > Hello everybody,
> >
> > First, I want to apologise for the fact that my previous message was
> > posted multiple times in this mailing list. Our sendmail log sent it
> > only once, so I do't really understand what went wrong.
> >
> > Back to the issue. Consider the following case we're dealing with in our
> > application:
> >
> > We're working on an e-commerce application with which people can order
> > different kind of products. Ordering a product consists of two parts:
> > first they have to fill in a product specific form to get a price quote
> > for the requested product. Then, if they accept the quote, they have to
> > fill in address information for delivery. Filling in address information
> > uses the same form for all different products.
> >
> > What we want to do is the following:
> > For each product, we define an action in struts-config.xml. Each action
> > uses an own, product specific form, say productAFrom, productBForm
> > etcetera. Each of these forms is an extension of an abstract class
> > productForm.
> > For the address information part, we want to define one additional
> > action in struts-config.xml, which uses the abstract productForm as
> > form-bean.
> >
> > Since filling in the address information form always follows the product
> > ordering form, we know that the user always has a productForm stored as
> > attribute in his session.
> >
> > I do realize that this mechanism gives some more responsibility to the
> > developer, in that he has to be careful using an abstract class name as
> > the type of a form bean, but I don't know any better alternatives yet.
> > Maybe using the same conventions as jsp:usebean, create a new instance
> > of an action form only if a 'class' attribute is present, if just a
> > 'type' attribute is present only try to recycle existing instances.
> >
> > Any suggestions?
> >
> > Ronald Bakker
> > Virgil PM&C
> >
> > "Craig R. McClanahan" wrote:
> > >
> > > On Mon, 6 Aug 2001, Ronald Bakker wrote:
> > >
> > > > Hi everybody,
> > > >
> > > > In Struts, form-beans can be described by 'name' and 'type'. Looking
> at
> > > > method 'processActionForm' in ActionServlet, I conclude that roughly
> the
> > > > following is happening (correct me if I'm wrong):
> > > >
> > > > When trying to find a form-bean from a mapping, Struts tries to find
> an
> > > > attribute with the given 'name' in the scope that is defined for this
> > > > mapping, if the class name of the found attribute is equal to 'type'
> it
> > > > will reuse this found attribute. Otherwise a new form-bean instance of
> > > > class 'type' is created and placed in scope.
> > > >
> > >
> > > That's a correct understanding.
> > >
> > > > To my opinion, one fallback of this implementation is that you are
> > > > forced to use the implementing class name of the form-bean you intend
> to
> > > > use, you are not able to use an interface or abstract class name. Is
> > > > there any chance Struts is going to use a more flexible way of
> > > > retrieving form-beans from a mapping? I would like Struts to use the
> > > > same mechanism as jsp:useBean, where you are more flexible in using
> > > > beans with  either 'type' or 'class'.
> > > >
> > >
> > > Remember that <jsp:useBean> has a restriction -- if the bean is not
> > > already there in the correct scope, you *must* have specified the actual
> > > class name so that <jsp:useBean> can instantiate it.  Struts will often
> > > (and, if you're using request scope form beans, *always*) need this
> > > information anyway, for the same reason.
> > >
> > > > Right now, we replaced this part of processActionForm with an own
> > > > mechanism of reusing form-beans:
> > > >
> > > > /**
> > > >  * Original Struts code:
> > > >  */
> > > >
> > > > // Can we recycle the existing form bean instance?
> > > > if ((instance != null) &&
> > > >   className.equals(instance.getClass().getName())) {
> > > >   if (debug >= 1) {
> > > >     log(" Recycling existing ActionForm bean instance of class '"
> > > >         + className + "'");
> > > >   }
> > > >
> > > >   return (instance);
> > > > }
> > > >
> > > > /**
> > > >  * Replaced by our code:
> > > >  */
> > > >
> > > > // Can we recycle the existing form bean instance?
> > > > try {
> > > >
> > > >   if ((instance != null) &&
> > > > Class.forName(className).isInstance(instance)) {
> > > >     if (debug >= 1) {
> > > >       log(" Recycling existing ActionForm bean instance of class '"
> > > >           + className + "'");
> > > >     }
> > > >     return (instance);
> > > >   }
> > > > }
> > > > catch (ClassNotFoundException ce) {
> > > >
> > > >   if (debug >= 1) {
> > > >     log(" Class not found: '" + className + "'");
> > > >   }
> > > >   return null;
> > > > }
> > > >
> > >
> > > I can see what you're after, but won't this only work in the case of
> > > session beans that were previously created by an Action?  For anyone
> else,
> > > you'll just get an instantiation error.
> > >
> > > Note to self -- if we change the logic here, a similar change will be
> > > needed inside the <html:form> tag, which can also create the form bean
> > > dynamically if needed.
> > >
> > > > Ronald Bakker
> > > > Virgil PM&C
> > > >
> > >
> > > Craig