I have Struts2 actions with different (HTML and JSON ) result types. They use common interceptor.
If needed to intercept the request, how to return result based on
In Struts2 the action has not a type. This means that you cannot configure the type of the action. Instead you can configure result types in the xml configuration. In the xml configuration file this is defined as the result-type
tag. When you configure the result using result
tag you specify type
attribute that will be used to determine the corresponding result type. Say name="success"
or name="error"
are results of the dispatcher
result type.
When the action is intercepted you could get the results
Map<String, ResultConfig> results = actionInvocation.getProxy().getConfig().getResults();
In the ResultConfig
there's className
attribute that could be used to determine the type of the result.
I have Struts2 actions with different (HTML and JSON ) result types. They use common interceptor. If need to intercept the request, how to return result based on given action result type?
For example, my Action.ERROR forwards to JSP page. If action is JSON type I want to forward JSON error instead. Please advice.
Although is true that an Action has not a type, it's also true that, if an Action is called in an AJAX way, like an action returning JSON, all of its results should have the same result type (JSON in this case), unless you are using a single Action to perform different logical actions (ajax and non-ajax operations, that is an anti-pattern);
That said, if you want to return the proper GLOBAL error result, from inside an Interceptor that is used by all of your Actions (each one with its result type), based on their other result type (let's say: SUCCESS
, assuming every Action has a SUCCESS
result), this is the way to do it:
public String intercept(ActionInvocation invocation) throws Exception {
// Get the action configuration defined in struts.xml
ActionConfig config = invocation.getProxy().getConfig();
// Get the SUCCESS result configured for that Action
ResultConfig success = config.getResults().get("success");
// Get the class of the SUCCESS result
Object clazz = success.getClass();
/* .... oops, some error occurred !!
We now need to redirect to the right global error result .... */
if (clazz instanceof org.apache.struts2.dispatcher.ServletDispatcherResult) {
log.debug("Struts2 Result type: CLASSIC");
return "error";
} else if (clazz instanceof org.apache.struts2.json.JSONResult) {
log.debug("Struts2 Result type: JSON");
return "jsonError";
} else {
log.debug("Struts2 Result type: SOMETHING ELSE, returning default ");
return "error";
}
}
Although this is technically possible, i would discourage it because... there is no real reason to do it;
For your purpose, remember that each global result is scoped in its <package>
;
Since you could (/should) have two different packages for Classic Actions (a <package>
extending struts-default
) and JSON Actions (a <package>
extending json-default
), you can simply define two different global error result for each package with the same name but different result type; this way the Interceptor will call the one relative to the package of the current Action, outputting the desired kind of result.