You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by "Irving, Dave" <Da...@logicacmg.com> on 2004/02/26 14:29:53 UTC

Removing business logic from Actions

Hi all,

Ive seen quite a few web applications employing Struts where business logic
is bolted straight in to Action classes. While not-so-bad for small
projects, this obviously can 'get out of hand' for large applications -
leading to poor maintainability, dependency on the web tier etc etc.
So, I got to thinking, what should an application specific struts Action
really be doing?
My interpretation of a 'standard case' boiled down to the following:

* Interpret an ActionForm to produce (a) business value object(s)
* Delegate to the 'business' layer to perform some functionality
* (Optionally) Interpret result and add elements to request / session to
facilitate view (optionally creating a view model from a returned business
object)
* (Optionall) Interpret result to find an appropriate forward

In my (limited) experience, it seems all too easy to extend the actions
responsibilities to cover things which should really be accomplished by the
business tier.
So I got to thinking about ways to 'channel' action development the right
way, and thought about a 'MediatorAction'.
MediatorAction accomplish the above 4 tasks in a declarative manner
(probably using an xml configuration file), and would rely heaviliy on the
use of Java Beans - in the same way as the struts custom tags.
As a quick example, lets suppose we have this rough action:

public class OrderAction extends Action {
  ...
  
  public ActionForward execute(...) {

    // Stage 1 - create business VO from form and potentially request
    ProductVO product = createProductRequest(form, request);

    // Stage 2 - invoke business layer
    OrderResult result = shop.orderProduct(product);

    // Interpret result
    if (result.getStatus().isSuccess()) {
      // Stage 3 - create view model from result (optional, could just use
'result')
      OrderDetails orderDetails = result.getDetails();
      request.setAttribute(ORDER_VIEW, orderDetails);
      
      // Stage 4 - we now know our mapping
      return mapping.findForward(SUCCESS);
    }
    else {
      // Stage 4 - we now know our mapping
      return mapping.findForward(FAILURE);
    }
  }
  ...
}
Lets assume MediatorAction exists. Here is partial configuration to show how
the same result could be acheived declaratively:

<mediatorAction path="/orders/PlaceOrder">
  <result property="status.success" value="true" forward="showOrderDetails"
>
    <export id="orderView" property="details" scope="request">
  </result>
  <result property="status.success" value="false" forward="failedOrder" />
</mediatorAction>

It can be seen that we can query the result of a business operation in an
'nested bean' manner to match a 'result', which in turn defines a forward,
and can optionall 'export' (or even remove) objects in a defined scope.

This is a simplified example. It may be that we wish to map a business
object in to a view model object before exporting it to a scope. E.g, we may
have an OrderViewModel which we wish to populate from the result. We would
have the ability to specifiy a 'ViewMapper' in the export element which
would enable custom conversion from a business object to the exported (view)
object.
Obviously, a 'BusinessMapper' would be installed to map from the Form /
Request to a business object to be provided to the configured business
delegate.

I think such a combination would enable 'typical' app specific struts
actions to be declared easily, and would reduce the chances of business
logic creeping in.
The 'mappers' would provide the targeted parametization to enable the action
to be used in a wide variety of contexts.

I would be really grateful for any feedback on this approach. I'd happily
develop it further / make it available if people think it would be useful.

This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.

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