net.sourceforge.stripes.controller
Class NameBasedActionResolver

java.lang.Object
  extended by net.sourceforge.stripes.controller.AnnotatedClassActionResolver
      extended by net.sourceforge.stripes.controller.NameBasedActionResolver
All Implemented Interfaces:
ConfigurableComponent, ActionResolver

public class NameBasedActionResolver
extends AnnotatedClassActionResolver

An ActionResolver that uses the names of classes and methods to generate sensible default URL bindings and event names respectively. Extends the default AnnotatedClassActionResolver, and is fully backward compatible. Any classes and methods that are annotated with UrlBinding and HandlesEvent will retain the bindings specified in those annotations. In the case when an annotation is absent then a default binding is generated.

The generation of ActionBean URL bindings is done by taking the class name and removing any extraneous packages at the front of the name, removing the strings "Action" and "Bean" from the end of the name, substituting slashes for periods and appending a suffix (.action by default). The set of packages that are trimmed is specified by the getBasePackages() method. By default this method returns the set [web, www, stripes, action]. These packages (and their parents) are removed from the class name. E.g. com.myco.web.foo.BarActionBean would become foo.BarActionBean. Continuing on, the list of Action Bean suffixes, specified by the getActionBeanSuffixes() method, are trimmed from the end of the Action Bean class name. With the defaults, [Bean, Action], we would trim foo.BarActionBean further to foo.Bar, and then translate it to /foo/Bar. Lastly the suffix returned by getBindingSuffix() is appended, giving the binding /foo/Bar.action.

The translation of class names into URL bindings is designed to be easy to override and customize. To that end you can easily change how this translation is done by overriding getBasePackages() and/or getBindingSuffix(), or completely customize the behaviour by overriding getUrlBinding(String).

Mapping of method names to event names is simpler. Again the parent class is delegated to in case the method is annotated. If it is not, and the method is a concrete public method that returns a Resolution (or subclass thereof) it is mapped to an event of the same name as the method. So an un-annotated method "public Resolution view()" is mapped to an event called "view". It should be noted that there is no special method name that signifies the default handler. If there is more than one handler and you require a default handler you must still mark the default method with @DefaultHandler.

Another useful feature of the NameBasedActionResolver is that when a request arrives for a URL that is not bound to an ActionBean the resolver will attempt to map the request to a view and return a 'dummy' ActionBean that will take the user to the view. The exact behaviour is modifiable by overriding one or more of handleActionBeanNotFound(ActionBeanContext, String), findView(String) or getFindViewAttempts(String). The default behaviour is to map the URL being requested to three potential JSP names/paths, check for the existence of a JSP at those locations and if one exists then to return an ActionBean that will render the view. For example if a user requested '/account/ViewAccount.action' but an ActionBean does not yet exist bound to that URL, the resolver will check for JSPs in the following order:

The value of this approach comes from the fact that by default all pages can appear to have a pre-action whether they actually have one or not. In the above can you might chose to link to /account/ViewAccount.action even though you know that no action exists and you want to navigate directly to a page. This way, if you later decide you do need a pre-action for any reason you can simply code the ActionBean and be done. No URLs or links need to be modified and all requests to /account/ViewAccount.action will flow through the ActionBean.

Since:
Stripes 1.2
Author:
Tim Fennell

Field Summary
static Set<String> BASE_PACKAGES
          Default set of packages (web, www, stripes, action) to be removed from the front of class names when translating them to URL bindings.
static List<String> DEFAULT_ACTION_BEAN_SUFFIXES
          Default list of suffixes (Bean, Action) to remove to the end of the Action Bean class name.
static String DEFAULT_BINDING_SUFFIX
          Default suffix (.action) to add to URL bindings.
 
Fields inherited from class net.sourceforge.stripes.controller.AnnotatedClassActionResolver
PACKAGES
 
Fields inherited from interface net.sourceforge.stripes.controller.ActionResolver
RESOLVED_ACTION
 
Constructor Summary
NameBasedActionResolver()
           
 
Method Summary
protected  Resolution findView(String urlBinding)
          Attempts to locate a default view for the urlBinding provided and return a ForwardResolution that will take the user to the view.
 ActionBean getActionBean(ActionBeanContext context, String urlBinding)
          Overridden to trap the exception that is thrown when a URL cannot be mapped to an ActionBean and then attempt to construct a dummy ActionBean that will forward the user to an appropriate view.
protected  List<String> getActionBeanSuffixes()
          Returns a list of suffixes to be removed from the end of the Action Bean class name, if present.
protected  Set<String> getBasePackages()
          Returns a set of package names (fully qualified or not) that should be removed from the start of a classname before translating the name into a URL Binding.
protected  String getBindingSuffix()
          Returns a non-null String suffix to be used when constructing URL bindings.
protected  List<String> getFindViewAttempts(String urlBinding)
          Returns the list of attempts to locate a default view for the urlBinding provided.
 String getHandledEvent(Method handler)
          First checks with the super class to see if an annotated event name is present, and if not then returns the name of the handler method itself.
 String getUrlBinding(Class<? extends ActionBean> clazz)
          Finds or generates the URL binding for the class supplied.
protected  String getUrlBinding(String name)
          Takes a class name and translates it into a URL binding by removing extraneous package names, removing Action, Bean, or ActionBean from the end of the class name if present, replacing periods with slashes, and appending a standard suffix as supplied by getBindingSuffix().
protected  ActionBean handleActionBeanNotFound(ActionBeanContext context, String urlBinding)
          Invoked when no appropriate ActionBean can be located.
 void init(Configuration configuration)
          First invokes the parent classes init() method and then quietly adds a specialized ActionBean to the set of ActionBeans the resolver is managing.
 
Methods inherited from class net.sourceforge.stripes.controller.AnnotatedClassActionResolver
addActionBean, assertGetContextWorks, findClasses, getActionBean, getActionBeanClasses, getActionBeanType, getConfiguration, getDefaultHandler, getEventName, getEventNameFromEventNameParam, getEventNameFromPath, getEventNameFromRequestAttribute, getEventNameFromRequestParams, getHandler, getRequestedPath, getUrlBindingFactory, getUrlBindingFromPath, makeNewActionBean, processMethods, removeActionBean, setActionBeanContext
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

BASE_PACKAGES

public static final Set<String> BASE_PACKAGES
Default set of packages (web, www, stripes, action) to be removed from the front of class names when translating them to URL bindings.


DEFAULT_BINDING_SUFFIX

public static final String DEFAULT_BINDING_SUFFIX
Default suffix (.action) to add to URL bindings.

See Also:
Constant Field Values

DEFAULT_ACTION_BEAN_SUFFIXES

public static final List<String> DEFAULT_ACTION_BEAN_SUFFIXES
Default list of suffixes (Bean, Action) to remove to the end of the Action Bean class name.

Constructor Detail

NameBasedActionResolver

public NameBasedActionResolver()
Method Detail

init

public void init(Configuration configuration)
          throws Exception
First invokes the parent classes init() method and then quietly adds a specialized ActionBean to the set of ActionBeans the resolver is managing. The "specialized" bean is one that is used when a bean is not bound to a URL, to then forward the user to an appropriate view if one exists.

Specified by:
init in interface ConfigurableComponent
Overrides:
init in class AnnotatedClassActionResolver
Parameters:
configuration - the Configuration object being used by Stripes
Throws:
Exception - should be thrown if the component cannot be configured well enough to use.

getUrlBinding

public String getUrlBinding(Class<? extends ActionBean> clazz)

Finds or generates the URL binding for the class supplied. First delegates to the parent class to see if an annotated url binding is present. If not, the class name is taken and translated into a URL binding using getUrlBinding(String name).

Specified by:
getUrlBinding in interface ActionResolver
Overrides:
getUrlBinding in class AnnotatedClassActionResolver
Parameters:
clazz - a Class representing an ActionBean
Returns:
the String URL binding for the ActionBean

getUrlBinding

protected String getUrlBinding(String name)
Takes a class name and translates it into a URL binding by removing extraneous package names, removing Action, Bean, or ActionBean from the end of the class name if present, replacing periods with slashes, and appending a standard suffix as supplied by getBindingSuffix().

For example the class com.myco.web.action.user.RegisterActionBean would be translated to /user/Register.action. The behaviour of this method can be overridden either directly or by overriding the methods getBindingSuffix() and getBasePackages() which are used by this method.

Parameters:
name - the name of the class to create a binding for
Returns:
a String URL binding for the class

getBasePackages

protected Set<String> getBasePackages()
Returns a set of package names (fully qualified or not) that should be removed from the start of a classname before translating the name into a URL Binding. By default returns "web", "www", "stripes" and "action".

Returns:
a non-null set of String package names.

getBindingSuffix

protected String getBindingSuffix()
Returns a non-null String suffix to be used when constructing URL bindings. The default is ".action".


getActionBeanSuffixes

protected List<String> getActionBeanSuffixes()
Returns a list of suffixes to be removed from the end of the Action Bean class name, if present. The defaults are ["Bean", "Action"].

Since:
Stripes 1.5

getHandledEvent

public String getHandledEvent(Method handler)
First checks with the super class to see if an annotated event name is present, and if not then returns the name of the handler method itself. Will return null for methods that do not return a resolution or are non-public or abstract.

Specified by:
getHandledEvent in interface ActionResolver
Overrides:
getHandledEvent in class AnnotatedClassActionResolver
Parameters:
handler - a method which may or may not be a handler method
Returns:
the name of the event handled, or null

getActionBean

public ActionBean getActionBean(ActionBeanContext context,
                                String urlBinding)
                         throws StripesServletException

Overridden to trap the exception that is thrown when a URL cannot be mapped to an ActionBean and then attempt to construct a dummy ActionBean that will forward the user to an appropriate view. In an exception is caught then the method handleActionBeanNotFound(ActionBeanContext, String) is invoked to handle the exception.

Specified by:
getActionBean in interface ActionResolver
Overrides:
getActionBean in class AnnotatedClassActionResolver
Parameters:
context - the ActionBeanContext of the current request
urlBinding - the urlBinding determined for the current request
Returns:
an ActionBean if there is an appropriate way to handle the request
Throws:
StripesServletException - if no ActionBean or alternate strategy can be found

handleActionBeanNotFound

protected ActionBean handleActionBeanNotFound(ActionBeanContext context,
                                              String urlBinding)
Invoked when no appropriate ActionBean can be located. Attempts to locate a view that is appropriate for this request by calling findView(String). If a view is found then a dummy ActionBean is constructed that will send the user to the view. If no appropriate view is found then null is returned.

Parameters:
context - the ActionBeanContext of the current request
urlBinding - the urlBinding determined for the current request
Returns:
an ActionBean that will render a view for the user, or null
Since:
Stripes 1.3

findView

protected Resolution findView(String urlBinding)

Attempts to locate a default view for the urlBinding provided and return a ForwardResolution that will take the user to the view. Looks for views by using the list of attempts returned by getFindViewAttempts(String).

For each view name derived a check is performed using ServletContext.getResource(String) to see if there is a file located at that URL. Only if a file actually exists will a Resolution be returned.

Can be overridden to provide a different kind of resolution. It is strongly recommended when overriding this method to check for the actual existence of views prior to manufacturing a resolution in order not to cause confusion when URLs are mistyped.

Parameters:
urlBinding - the url being accessed by the client in the current request
Returns:
a Resolution if a default view can be found, or null otherwise
Since:
Stripes 1.3

getFindViewAttempts

protected List<String> getFindViewAttempts(String urlBinding)

Returns the list of attempts to locate a default view for the urlBinding provided. Generates attempts for views by converting the incoming urlBinding with the following rules. For example if the urlBinding is '/account/ViewAccount.action' the following views will be returned in order:

Can be overridden to look for views with a different pattern.

Parameters:
urlBinding - the url being accessed by the client in the current request
Since:
Stripes 1.5


© Copyright 2005-2006, Stripes Development Team.