List- I'm looking for ideas on implementing a published interface for action mappings. By publishing an interface, I mean to define (preferably in the action mapping itself) what parameters the action class is expecting to be available, to avoid having to scan through the class to determine what parameters it is expecting in the request. I've recently discovered the <set-property> tag (I'm always the last to know.) for defining attributes of a mapping outside the struts-config DTD.
After playing around with the idea for a few hours, I came up with the following: Extended mapping- ------------------------------- First step is to extend the ActionMapping class. In addition to the stand action mapping properties and method, you will define a bean pattern for property "params". Because there are N-number of params possible, the implementation of this property would be something like: < ExtendedActionMapping.java > public class ExtendedActionMapping extends ActionMapping { protected ArrayList params = new ArrayList(); public void setParams(String value) { params.add(value); } public String[] getParams() { return (params.toArray(new String[params.size()])); } } < / ExtendedActionMapping.java > The web.xml for your action servlet should be modified to specify this class for your action mapping. Now that you've got this mapping set, the digester can process a mapping like: <action path="/blah" type="MyAction"> <set-property property="params" value="A-PARAM"/> </action> Dynamic params- ------------------------------- Because the set-property interface allows you to specify only a property and it's string value, it's necessary to provide a means to define more detail about your params. For example- your param could be expected as a request parameter, or possibly as a property of a session-scoped form bean unassociated with the mapping you are defining. It would also be nice if the actual param values were provided to the action instead of just the name of the variables. So- instead of using <set-property> to declare just the variable name, we get a little fancy. We'll use an expression which can be matched to an RE pattern. For example, my action below is expecting a parameter (in the request scope) called "locationId": <action path="/blah" type="MyAction"> <set-property property="params" value="request{locationId}"/> <set-property property="params" value="form{loginForm, userId}"/> </action> This string/expression "request{locationId}" will be available as a param in the mapping instance. What good does that do us you might ask? Well, we'll need to examine this "expression" and somehow retrieve the value it refers to. To accomplish this, we'll need to sub-class a base action which has implemented functionality to deal with these expressions. To help us parse the expressions we have the following classes: Params - a collection of Param instances. Params implements a "findParam" method which matches an expression to a param instance: findParam(expression) returns a Param Param - an interface defining 2 methods: getPattern()- returns a regular expression pattern which matches expressions this param is capable of handling getValue(expression, request)- parses the expression and uses the request scope to retrieve the param value from whatever source necessary. Here's a param example: public class RequestParam implements Param { protected String pattern = "^request{([A-Za-z]*)}$"; public String getPattern() { return this.pattern; } public String getName(expression) { RE re = new RE(getPattern()); re.match(expression); return (re.getParen(1)); } public String getValue(String expression, HttpRequest request) { RE re = new RE(getPattern()); re.match(expression); String paramName = re.getParen(1); return (request.getParameter(paramName)); } } The pattern for this class ("^request{([A-Za-z]*)}$") will match an expression like: "request{locationId}". The responsibility of the Params instance is to match this class with the defined param. Our RequestParam class is then capable of parsing this expression to determine the name of the desired request parameter. A similar implementation of this would be to retrieve properties of form beans using a pattern like: "form{FORM-NAME, PROPERTY}". Within the FormBeanParam class we would parse the expression to determine that form bean name and the desired property. We could then use the PropertyUtils to retrieve this value. BaseAction- ------------------------ So back to our BaseAction implementation. The BaseAction will hold an instance of the params collection. By placing the base action first in the execution chain (i.e. by defining execute(mapping, form, request, response)) we have our processing hook. So we perform something like this: public class BaseAction extends Action { protected Params params = new Params(); public BaseAction() { params.addParam(new RequestParam()); params.addParam(new FormBeanParam()); } public ActionForward execute(mapping, form, request, response) { Hashtable paramMap = new Hashtable(); if (mapping.getParams().length > 0) { String[] params = mapping.getParams(); for (int i = 0; i < params.length; i++) { String expression = params[i]; Param param = params.findParam(expression); paramMap.put(param.getName(expression), param.getValue(expression)); } } // Now we call our super-class action implementation, with our paramMap in the signature. return (super.execute(mapping, form, paramMap, request, response)); } } So within our action, we now have a map of our expected parameters. Within the base action, we might have thrown an exception or something if an expected param could not be discovered, this negates the need for any logic to check for the existance of parameters or the like within our action class. Because we are using patterns to create a relationship to our parameter logic, it's an easy matter to add another attribute to the expression which declares a variable to be required, or not. You could even define what exception is thrown when a parameter is not present (but that would be going a little overboard) Within our system at work, we use a method similar to this (just not as flexible) to identify constants as parameters to actions. For example, when building a link like: <a href="/someaction.do?param=USER_ID">link</a> One would generally need either a tag or some script to look up the user id and add it to the link. What we've done instead is match this parameter value to a logic implementation which is capable of returning the user id value, and this behavior is completely transparent. Any ideas? Responses? thanks Jason Stiefel [EMAIL PROTECTED] -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>