<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>devedup.com &#187; struts 2</title>
	<atom:link href="http://blog.devedup.com/index.php/category/struts-2/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.devedup.com</link>
	<description></description>
	<lastBuildDate>Sun, 09 Oct 2011 16:00:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Custom Struts 2 ActionMapper</title>
		<link>http://blog.devedup.com/index.php/2009/06/11/custom-struts-2-actionmapper/</link>
		<comments>http://blog.devedup.com/index.php/2009/06/11/custom-struts-2-actionmapper/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 17:31:58 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[struts 2]]></category>
		<category><![CDATA[ActionMapper]]></category>

		<guid isPermaLink="false">http://blog.devedup.com/?p=84</guid>
		<description><![CDATA[The ActionMapper is the component that maps a url onto one of your action classes. More information can be found about it here: http://struts.apache.org/2.1.6/docs/actionmapper.html In most applications you won&#8217;t need to change the default ActionMapper. A project I am currently working on required that I implement an API specified by a 3rd party. The requests [...]]]></description>
			<content:encoded><![CDATA[<p>The ActionMapper is the component that maps a url onto one of your action classes. More information can be found about it here:</p>
<p><a href="http://struts.apache.org/2.1.6/docs/actionmapper.html">http://struts.apache.org/2.1.6/docs/actionmapper.html</a></p>
<p>In most applications you won&#8217;t need to change the default ActionMapper. A project I am currently working on required that I implement an API specified by a 3rd party. The requests that they send us are all POST requests over HTTPS. Nothing fancy. To determine which method/procedure that they want to call, they send a parameter on the request named &#8216;function&#8217;. I decided that I would implement the receiving service using Struts 2 and create a custom ActionMapper. I did a search, but the results didn&#8217;t show any examples of creating a custom ActionMapper, so I downloaded the  struts 2 source to see how the default one worked, and then I constructed mine with that as a &#8216;guide&#8217;.</p>
<p>My implementation is rather basic, as it isn&#8217;t such a complex requirement.:</p>
<pre class="brush: java;">import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import org.apache.log4j.Logger;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

public class SyncActionMapper implements ActionMapper {

    private final Logger LOG = Logger.getLogger(getClass());

    private static final String UNKNOW_FUNCTION_MAPPING = &quot;unknownFunction&quot;;

    @Override
    public ActionMapping getMapping(HttpServletRequest request,
                              ConfigurationManager configurationManager) {
        Map&amp;lt;String, ActionConfig&amp;gt; actions =
           configurationManager.getConfiguration().
              getPackageConfig(&quot;sync-facade&quot;).getActionConfigs();

        ActionMapping mapping = new ActionMapping();
        mapping.setNamespace(&quot;/&quot;);

        String actionName = request.getParameter(&quot;function&quot;);
        if (actionName == null || actionName.length() &amp;lt; 1) {
            LOG.error(&quot;function param no found on request &quot; + actionName);
            actionName = UNKNOW_FUNCTION_MAPPING;
        } else if (!actions.containsKey(actionName)) {
            LOG.error(&quot;action not found in struts.xml &quot; + actionName);
            actionName = UNKNOW_FUNCTION_MAPPING;
        } else {
            if (LOG.isDebugEnabled()) {
                LOG.debug(&quot;function param found, &quot;
                    + &quot; mapping to action with the name: &quot; + actionName);
            }
        }
        mapping.setName(actionName);
        return mapping;
    }

    @Override
    public ActionMapping getMappingFromActionName(String actionName) {
        ActionMapping mapping = new ActionMapping();
        mapping.setName(actionName);
        mapping.setNamespace(&quot;/&quot;);
        return mapping;
    }

    @Override
    public String getUriFromActionMapping(ActionMapping actionMapping) {
        throw new IllegalStateException(&quot;not implemented&quot;);
    }
}</pre>
<p>I also wanted to map unknown functions to an error action. Checking the struts.xml file and returning a valid ActionMapping is not part of the ActionMapper contract (so the docs say), but I decided to add this here. After getting the function name, I check to see if this function exists in struts.xml using the ConfigurationManager (i may need to optimize this line of code, not sure yet).</p>
<p>To set my custom ActionMapper to be the default I added a reference to it in struts.xml:</p>
<pre class="brush: xml;">&lt;constant name=&quot;struts.mapper.class&quot;
    value=&quot;com.devedup.sync.dispatcher.mapper.SyncActionMapper&quot;/&gt;</pre>
<p>I can now map to actions simply from the url http://localhost/myapp?function=myAction  (or similarly with the function param in the body of the POST request).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.devedup.com/index.php/2009/06/11/custom-struts-2-actionmapper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

