Use Defaults More

This page walks through techniques that can be used in Stripes to reduce the amount of configuration (usually in the form of annotation) that is necessary on a per-ActionBean basis.

URL Bindings and Event Names

Starting with Stripes 1.2 Stripes ships with a class called NameBasedActionResolver which is an extension to the default AnnotatedClassActionResolver. The NameBasedActionResolver will automatically create default URL bindings and event names where there are no annotations present. When annotations are present they take precedence.

The set of rules used to generate URL bindings are quite simple:

  1. Take the fully qualified class name
  2. Remove any extra package names from the from (more on this in a minute)
  3. Remove ActionBean or Action or Bean from the end of the class name if present
  4. Replace periods with slashes
  5. Append ".action"

A few examples should make this clearer:

Class Name

URL Binding

com.myco.web.RegisterActionBean

/Register.action

com.myco.www.user.RegisterAction

/user/Register.action

com.companyb.projectb.web.stripes.admin.MainAction

/admin/Main.action

The package name is truncated by removing the packages up until any of a set of "base packages" is encountered. By default that set of packages is: "web", "www", "stripes", "action".

It is possible to extend the NameBasedActionResolver to modify the rules used to generate the URL bindings. Changing the set of packages or the suffix used is trivial. For example:

A customized action resolver
public class MyActionResolver extends NameBasedActionResolver { 
	@Override 
	public Set<String> getBasePackages() { return Literal.set("ui", "client"); } 
	@Override 
	public String getBindingSuffix() { return ".do"; /* ugh */ } 
} 

This will result in mappings like com.companyz.accounts.ui.ledger.GeneralLedgerActionBean to /ledger/GeneralLedger.do. You can completely customize the generation of URL bindings by overriding getUrlBinding(String className).

The NameBasedActionResolver will also map events for all public methods that return a Resolution (excluding those which are annotated with @HandlesEvent). The event name is simply the name of the method in this case.

To see how to configure an alternate ActionResolver take a look at the Configuration Reference.

Automatic Type Conversion

It seems reasonably common to find simple domain classes that are similar to built in Java types, for example Money classes are often wrappers around BigDecimal and EmailAddress classes are often wrappers around a single String. It might be quite tempting to use the Java types in your ActionBean and convert them to your custom types in your handler method. The downside here is repeated code and probably repeated validation annotations.

Now, if you created your own TypeConverter you could use it by attaching a single annotation to your property:

@Validate(converter=MoneyTypeConverter.class) 
private Money balance; 

But that's sub-optimal! This might seem like the easy route, but when you start using the same Money class in lots of actions you'll have to keep repeating this. Instead you could create your own custom TypeConverterFactory. This will make Stripes aware of the Money type so that it will automatically convert it whenever it sees it. The easiest way to do this is to extend the built in DefaultTypeConverterFactory, for example:

A custom TypeConverterFactory
public class CustomTypeConverterFactory extends DefaultTypeConverterFactory { 
	public void init(Configuration configuration) { 
		super.init(configuration); 
		add(Money.class, MoneyTypeConverter.class); 
	} 
} 

To see how to configure an alternate TypeConverterFactory take a look at the Configuration Reference.