"Action-driven component-based opensource web application framework"
ActionServlet
version 0.94.2

ActionServlet Design Guidelines

1. Create reusable components!

  • Do not use Context for retrieving HTTP parameter values, if possible. Use parameter passing provided by ActionServlet instead.

    Example: non-reusable component

    public MyComponent {
       public void someMethod(Context context) {
          String parameter = context.get("someParameter");
          // do something...
       }
    }
    Example: reusable component

    public MyComponent {
       public void someMethod(String parameter) {
          // do something...
       }
    }
    Advantage: You can map any HTTP parameter of any name to the formal parameter of the method - in ActionConfig by <action> element:
    <action name="ActionName" method="someMethod(String HTTPParameterName)"/>
  • Do not use Context for assigning $variables.

    Example: non-reusable component

    public MyComponent {
       public void someMethod(Context context) {
          // do something...
          context.put("variable", someValue);
       }
    }
    Example: reusable component

    public MyComponent {
       public int someMethod() {
          // do something...
          return someValue;
       }
    }
    Advantage: You can map return value to any $variable without changing the component's code in ActionConfig by <on-return> element:
    <on-return value="*" assign-to="variable" show-template="..."/>

    Note: <output-variable> element can be also used to set $variables.

2. Use <properties> to setup your components!

Example: component using proprietary solution

public DbComponent {
   private int maxDbConnections;
   
   public DbComponent() {
      maxDbConnections = Integer.parseInt(System.getProperty("max.db.connections"));
   }
}
Example: solution using <properties> and JavaBeansInstantiator

public DbComponent {
   private int maxDbConnections;
   
   public void setMaxDbConnections(int value) {
      maxDbConnections = value;
   }
}

<properties>
   <property component="DbComponent" name="MaxDbConnections" value="5"/>
</properties>

<components>
   <component class="DbComponent" name="DbComponent"/>
</components>
Advantage: You can supply configuration for each component without risking namespace conflicts.

Note: Custom initialization (of Corba object, EJBs etc.) can be done by instantiators (see Specification).

3. Use type handlers for conversions to custom types!

Example: hard coded solution

public MyComponent {
   public void someMethod(String email) {
      // parse string to get recipient name and his/her address, ...
      // (this must be done by each component class handling email)
   }
}
Example: solution with type handler

public class EmailHandler implements SimpleTypeHandler {
   public Object convert(Context context, String email) 
   throws ConversionException {
      return new Email(email);   // Email does parsing
   }
}

public MyComponent {
   public void someMethod(Email email) {
      String recipient = email.getRecipient();
      String address = email.getAddress();
      // ...
   }
}
Advantage: You delegate proper type conversion to classes that know their types.

Note: You must bind type handler to its type in ActionConfig:

<type-handler target-type="Email" class="EmailHandler"/>