You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Rogério Saran <rs...@organox.com.br> on 2001/02/15 20:46:19 UTC

Newbie: overall application architecture

I am a bit afraid of addressing stuff already discussed, but I was not
able to solve this question with the struts documentation or the list archives.

On the past week I built a small site to evaluate Struts to be used on
our development effort. We intend to built a content aggregation portal
in Brazil, expecting to gather considerable traffic. At the same time we
started the project and begin to look at java web technologies.

We began with some poorly structured JSP model 1 code and lots of
scriptlets. On our  second "development round" we deployed an
application with a "hand-written" model 2 structure where a controller
servlet map all events to its own action methods and those select the
correct view depending on application state.

The whole application runs on this single controller servlet, and it is
responsible for instantiating the "model" as  private variables. JSPs
are used strictly to take care of views and they get their input from
beans placed at request or session scope.

I tried to follow these rules to build my test site with Struts. Valid
user response is always carried by action mappings, all input validation
is done by formbean, all controlling logic is placed on action classes
and all views are handled by "logical" forwards. Is works fairly well,
but depends on "loose" couplings - the developer is responsible for
mantaining a clean model. These are not real "flaws" but take the user
away from the desired mvc approach.

I can point some relevant topics. Some of them may be just a case of bad
framework usage, and for those I definitely want some help. Other may be
real issues  on Struts ability to handle complex applications.

I - Actions and Roles
=====================
The action mapping mechanics seems to be a-ok to reach the MVC paradigm.
Each action class can be coded separately and do its own task handling.
I got some problems however, trying to make several action classes
handle some common funcionality. In my sample app each action class end
its processing by choosing the view to be presented. This way the action
should check for authentication, i18n and related stuff. All actions
available to "logged" users are calling some common code to do so.

Struts could handle this situation by itself with some "action chaining"
construct, like declararing "action filters" or "roles" on the
struts-config action tag. The former is a generic approach to handle
"ok, you want this action to be performed but... first we will do some
check on model state to see if it is valid". The second is a direct
approach to solve the authentication problem. Struts would carry a role
setting for each user session and actions would be screened by these
roles. This is not a formbean-based screening, but a model-based.


II - Strict Control Channeling and FSMs
=======================================
My sample site does not allow user to render JSPs directly. On this
approach every user request should be handled by the controller servlet.
This allow seeing the web application as a finite state machine where
every state transition is handled and can be accounted by the controller
servlet. As JSPs get their data from beans on session or request scope
they shoud not be called directly by the user. This would be an
unaccounted state change, to be avoided by all means.

This design goal would require to every possible view to be listed as
logical forwards, and those logical forwards binded to the action
classes on the struts-config descriptor. One way to do it is shown on
the Struts sample: the application mapping provide some "properties"
filled with data from the action settings.

A suggestion is to provide mechanics to define all "hard" forwards (real
URLs) on the global forwards section, and refer it on "set-properties"
for each action definition. This way the path and name of the views
would be set only once in the application. Nobody needs to know the
application is showing "/jsp/index.jsp?skin=default" (the logical
forward destination). They just want to see "indexpage" (a logical
forward), and this is result of "home.do" or "login.do" (action
mappings). Only those actions should "see" these forwards, and an
explicit declaration on struts-config would improve the implementation,
ensuring good design.

III - Separating View Logic from Controller Logic
=================================================
The Stuts taglib is fairly extensive, but offer very little binding with
the controller design. This is actually good; all a JSP should "see" on
our MVC implementation is "data to be viewed", passed to the JSP though
beans on the request/session context.

What troubled us is the suggestion on the sample application to add tags
handling controller or model logic. The "app:checkLogon" definitely is
not handling viewing tasks. It checks the "model" for authentication,
then do "controller" tasks redirecting the user to another page. This is
a patch for non-mvc behaviour, where the "action" is a direct reference
to the JSP and the "control" is a bunch of code hidden on tags. If
somebody forget a tag it is broken. You also cannot use static content
because your "view" should be able to do controller processing.

The origin for this "design flaw" is lack of controller support when the
user requests a JSP document directly.

Another issue on binding view and controller logic: if all possible
controller states (actions) and views (forwards) are stored on
struts-config, it is reasonable to provide some mechanics to allow a JSP
to know about it. Instead of placing "hard" links on the page, only
valid actions should be used and referred, like <a
href="/logoff.do">click here to logoff</a>.

This is not handled by Struts as I know; any JSP can referr any action.
I am not shure how it could be done but would be nice to see a list of
valid transitions for each view on struts-config. Again this would
improve cleanliness.

IV - Template Handling and Tag Behavior
=======================================
The template tags really rocks! To make them still better, I have 2
suggestions: a) add body tag support for the "put" tag, allowing the
user to place "inline" content on a template call and b) create a
mechanism to pass template parameters to other struts tags - if I pass a
string property id through a template the resulting get tag will render
the result text on the page response.

What I want is to pass the template parameter to the bean:message tag.
Making this tag able to take input from its body text or the key
parameter is enough to solve the problem. This can be solved using
bean:define, but rendering through body tag support is a direct and
bombproof approach.



*Saran

Re: Newbie: overall application architecture

Posted by ma...@tumbleweed.com.
At 05:46 PM 2/15/01 -0200, Rogério Saran wrote:
>Struts could handle this situation by itself with some "action chaining"
>construct, like declararing "action filters" or "roles" on the
>struts-config action tag. The former is a generic approach to handle
>"ok, you want this action to be performed but... first we will do some
>check on model state to see if it is valid". The second is a direct
>approach to solve the authentication problem. Struts would carry a role
>setting for each user session and actions would be screened by these
>roles. This is not a formbean-based screening, but a model-based.

What we do is subclass ActionServlet and override a couple of methods to 
perform an authentication check before going ahead with the action itself. 
I think this is a fairly common approach with Struts today.

On the subject of roles, you may be interested to know that there is an 
item on the Struts 1.1 ToDo list entitled "Role-Based Action Execution".

>A suggestion is to provide mechanics to define all "hard" forwards (real
>URLs) on the global forwards section, and refer it on "set-properties"
>for each action definition. This way the path and name of the views
>would be set only once in the application. Nobody needs to know the
>application is showing "/jsp/index.jsp?skin=default" (the logical
>forward destination). They just want to see "indexpage" (a logical
>forward), and this is result of "home.do" or "login.do" (action
>mappings). Only those actions should "see" these forwards, and an
>explicit declaration on struts-config would improve the implementation,
>ensuring good design.

I'm not sure I understand this completely, but let me see. I think you are 
suggesting that all forwards are defined as global forwards, and that each 
action declare the list of forwards (by name only) that it uses. Are you 
also suggesting that this list be a constraint on the action? That is, an 
action can use *only* the forwards listed in its section of struts-config?

You could, of course, partially achieve this with Struts today by always 
using global forwards, and using comments to document which ones are 
invoked from each action. This obviously won't handle enforcement, though.

Personally, I wouldn't want to go this way. I prefer to make use of local 
forwards because it increases locality. All the information for an action 
is encapsulated in that one <action> section of struts-config. I know that 
the forwards defined there can't be invoked from any other action, which is 
something I cannot tell if all forwards are global.

>What troubled us is the suggestion on the sample application to add tags
>handling controller or model logic. The "app:checkLogon" definitely is
>not handling viewing tasks. It checks the "model" for authentication,
>then do "controller" tasks redirecting the user to another page. This is
>a patch for non-mvc behaviour, where the "action" is a direct reference
>to the JSP and the "control" is a bunch of code hidden on tags. If
>somebody forget a tag it is broken. You also cannot use static content
>because your "view" should be able to do controller processing.
>
>The origin for this "design flaw" is lack of controller support when the
>user requests a JSP document directly.

I agree this is ugly, although it's not really a Struts issue so much as a 
Servlets 2.2 issue, as I understand it. Unfortunately, I don't know of a 
good solution. Filters in Servlets 2.3 might provide a way, though.

--
Martin Cooper
Tumbleweed Communications