What's new? | Help | Directory | Sign in
Google
                
Search
for
Updated Nov 02, 2007 by bpontarelli
TechnicalSpecification  
One-sentence summary of this page.

Introduction

This document is a technical specification for how SmartURLs and possibly the new convention plugin for Struts2 functions and the requirements it has.

Definitions

Here are the definitions for terms used in this document. Plural forms of these are also used.

Term Definition
xwork-package An XWork configuration package that is defined in either the xwork or Struts 2 XML configuration files (not a Java package)
java-package A Java package that contains classes as defined by the Java language and Java virtual machine specifications.
sub-java-package A Java package with a parent java-package (i.e. com.example is the parent of com.example.sub) that contains sub-java-packages and/or action-classes.
action-package-identifier A identifier that is used to locate java-packages that contain action-classes and sub-java-packages.
action-class A Java class that handles an HTTP request and provides an HTTP response. This process is also known as handling an action.
action-name The name passed in via the HTTP request and used to find and invoke the correct action-class.
action-namespace The portion of the HTTP request path that denotes the namespace that the action is defined in. This is defined in detail in the URL mapping section.
action-transformation The process by which an action-name is translated into an action-class or vice versa.
namespace-transformation The process by which an action-namespace is translated into a java-package or vice versa.
view-result A JSP, FreeMarker template, Velocity template or other type of result that generates an HTTP response, usually a text based response containing HTML, XML, or some other type of text.

Requirements

  • Allow URLs to directly map to action-classes and view-results based on a standardized convention
  • Provide the ability to modify the conventions using annotations
  • Support the ability to define all the configuration that xwork-packages currently support including: interceptors, interceptor-refs, namespaces, extensions, default actions, default results, default interceptor stacks, expection and result types

URL Mapping

URLs should map directly to action-classes and view-results in a convention based manner. This can be provided on demand when an HTTP request comes into Struts or during application initialization such that the URLs that will be handled by the convention plugin are known prior to handling the first HTTP request.

URL Form

The convention plugin assumes the use of the standard J2EE URL form of:

http://www.example.com/context/namespace/resource/extra

Here are the definitions for the URL parts excluding 'http://www.example.com' (the HTTP schema and host):

|
Part Definition
context The J2EE web application context path
namespace Everything in the URL path excluding the J2EE application context path and the resource. This could be empty or any number of path elements separated by forward slash characters (/).
resource The resource being requested
extra Any additional information that is passed to the resource being requested. This is often used in lieu of HTTP request parameters for RESTful WebServices.

The BNF form for the URL is then:

<url> ::= <schema> '://' <host> [<context>] [<namespace>] <resource> [<extra>]
<schema> ::= 'http' | 'https'
<host> ::= // standard host definition
<context> ::= '/' identifier
<namespace> ::= <namespace> | '/' identifier <namespace>
<resource> ::= '/' identifier | '/'
<extra> :: = <extra> | '/' identifier <extra>

TODO the current extra definition might not be the best solution for REST.

The namespace part of the URL directly maps to the action-namespace definition above. The resource part of the URL directly maps to the action-name definition above and in turn translates to the action-class via the action-transformation.

TODO Define how the extra part of the URL is handled.

Java Packages

An application that uses the plugin will contain any number of java-packages and sub-java-packages that contain action-classes. All java-packages and sub-java-packages are located using action-package-identifiers.

Package Identifiers

A configuration parameter named struts.action.package.identifiers will define a comma separated list of action-package-identifiers. These identifiers are partial package names according the Java language specification. For example, given this Java package:

package com.example.actions;

the Strings com, example, and actions are all partial package names.

The action-package-identifiers will be the root Java package from which action-classes and sub-java-packages will be located. There default value for this configuration parameter will be:

struts.action.package.identifiers=struts,struts2,action,actions

Mapping

By default, java-packages will map to the action-namespace and vice-versa. This mapping occurs via a namespace-transformation process.

To illustrate this process, java-packages will be transformed into action-namespaces. This process would be indicative of implementations that pre-configure action-classes and view-results prior to the first request rather than locating action-classes or view-results based on the incoming URL.

Namespace Transformation

Here are the steps for namespace transformation.

  1. Find all Java packages in the application classpath that contain an action-package-identifier
  2. For each package, cut all characters prior to and including the action-package-identifier
  3. For each partial package name after the action-package-identifier convert from camel-case syntax to SEO syntax using this process
    1. Iterate over each character until an uppercase character is found
    2. If the uppercase character is the first character of the action-class name, convert it to lowercase and start processing the next character at step #1
    3. Insert a dash (-) character prior to the uppercase character
    4. If the character immediately following the uppercase character is lowercase, convert the uppercase character to lowercase
    5. If the character immediately following the uppercase character is uppercase, iterate over the uppercase characters converting each to lowercase until the first lowercase character is found or the String ends. Then, if there is a lowercase character, insert a dash (-) character prior to the lowercase character
    6. Repeat until the String ends
  4. Replace all instances of the dot (.) character with forward slash (/) characters
  5. Add a forward slash (/) character to the beginning of the result

Here are some examples of this process:

1. "com.example.actions"
2. ""
3. Skip this step
4. ""
5. "/"
1. "com.example.actions.foo"
2. "foo"
3. Skip this step
4. "foo"
5. "/foo"
1. "com.example.actions.fooBar"
2. "fooBar"
3.2. "foo-Bar"
3.3. "foo-bar"
4. "foo-bar"
5. "/foo-bar"
1. "com.example.actions.fooBAR"
2. "fooBar"
3.2. "foo-BAR"
3.4. "foo-bar"
4. "foo-bar"
5. "/foo-bar"

Java Classes

An application that uses the plugin will contain any number of action-classes, which will be defined in a java-package. Action-classes are determined in one of two ways:

  • The Java class name ends with the String "Action"
  • The Java class implements the com.opensymphony.xwork2.Action interface

Mapping

These action-classes will directly map to action-names using the action-transformation. Here are the steps for transforming an action-class to action-name.

  1. If the String ends in the word "Action", remove "Action" from the end of the String
  2. Iterate over each character until an uppercase character is found
  3. If the uppercase character is the first character of the action-class name, convert it to lowercase and start processing the next character at step #2
  4. Insert a dash (-) character prior to the uppercase character
  5. If the character immediately following the uppercase character is lowercase, convert the uppercase character to lowercase
  6. If the character immediately following the uppercase character is uppercase, iterate over the uppercase characters converting each to lowercase until the first lowercase character is found or the String ends. Then, if there is a lowercase character, insert a dash (-) character prior to the lowercase character
  7. Repeat at step #2 until the String ends

Examples

Here are some examples of converting action-class names to action-names.

"MyAction"
1. "My"
2. "my"
"MySecondAction"
1. "MySecond"
2. "mySecond"
3. "my-Second"
4. "my-second"
"MyURLAction"
1. "MyURL"
2. "myURL"
3. "my-URL"
4. "my-url"
"DisplayAllUsers"
1. "DisplayAllUsers"
2. "displayAllUsers"
3. "display-AllUsers"
4. "display-allUsers"
2. "display-allUsers"
3. "display-all-Users"
4. "display-all-users"

Complete Examples

Here are a few examples of a fully qualified class name and how it is transformed into a complete URL path. Each step is not spelled out as above for brevity.

Class: com.example.actions.admin.users.ListAllUsersAction
URL: /admin/users/list-all-users

Class: com.example.struts2.twoWords.SomeURL
URL: /two-words/some-url

Results

The plugin will handle view-results in two different manners.

  • As results of an action-class being executed by Struts
  • As the result of a URL request that has no action association

In both cases, the plugin will map results to URLs based on the location of the view-result or the incoming URL. However, if an action-class is executed for the URL, the result code from the action-class execution will also be used in locating the appropriate view-result.

Base Result Location

TODO

Mapping

TODO

Action Invocation

Once the fully qualified Java class names are converted to URL paths or vice versa, the plugin will now exactly which action-class is associated with a specific URL. The framework will execute that action-class when the URL is requested.

Search hierarchy


Sign in to add a comment