[
https://issues.apache.org/struts/browse/WW-3068?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Musachy Barroso resolved WW-3068.
---------------------------------
Resolution: Fixed
Fix Version/s: 2.1.7
The solution is to create a FreeMarker result and delegate the rendering to it,
instead of creating a FreeMarkerResult and adding it to the config (which
causes the exception)
> ExecuteAndWaitInterceptor
> org.apache.struts2.interceptor.ExecuteAndWaitInterceptor.doIntercept(ExecuteAndWaitInterceptor.java:256)
> -----------------------------------------------------------------------------------------------------------------------------------
>
> Key: WW-3068
> URL: https://issues.apache.org/struts/browse/WW-3068
> Project: Struts 2
> Issue Type: Bug
> Environment: Struts-2.1.6
> TC 6.0.14
> JDK 1.6.0_10
> > Subject: Re: ExecuteAndWaitInterceptor not working (2.1.6)
> > > execAndWait in 2.1.6 gives the following exception when it kicks in:
> > > (code pasted below)
> > >
> > >
> > > java.lang.UnsupportedOperationException
> > > ??? java.util.Collections$UnmodifiableMap.put(Collections.java:1285)
> > > ???
> > > org.apache.struts2.interceptor.ExecuteAndWaitInterceptor.doIntercept(ExecuteAndWaitInterceptor.java:256)
> >
> Reporter: Martin Gainty
> Fix For: 2.1.7
>
>
> public static final String WAIT = "wait";
> org.apache.struts2.interceptor.ExecuteAndWaitInterceptor.java
> .............
> protected String doIntercept(ActionInvocation actionInvocation) throws
> Exception {
> ..............
> //sync on the real HttpSession as the session from the context is a wrap
> that is created
> //on every request
> synchronized (httpSession)
> {
> BackgroundProcess bp = (BackgroundProcess) session.get(KEY +
> name);
> if ((!executeAfterValidationPass || secondTime) && bp == null)
> {
> bp = getNewBackgroundProcess(name, actionInvocation,
> threadPriority);
> session.put(KEY + name, bp);
> performInitialDelay(bp); // first time let some time pass
> before showing wait page
> secondTime = false;
> }
> if ((!executeAfterValidationPass || !secondTime) && bp != null &&
> !bp.isDone()) {
> actionInvocation.getStack().push(bp.getAction());
> Map results = proxy.getConfig().getResults();
> if (!results.containsKey(WAIT)) {
> LOG.warn("ExecuteAndWait interceptor has detected that no
> result named 'wait' is available. " +
> "Defaulting to a plain built-in wait page. It is
> highly recommend you " +
> "provide an action-specific or global result
> named '" + WAIT +
> "'! This requires FreeMarker support and won't
> work if you don't have it installed");
> // no wait result? hmm -- let's try to do dynamically put
> it in for you!
> ResultConfig rc = new ResultConfig.Builder(WAIT,
> "org.apache.struts2.views.freemarker.FreemarkerResult")
> .addParams(Collections.singletonMap("location",
> "/org/apache/struts2/interceptor/wait.ftl"))
> .build();
> /************ABOVE CODE causes abend************/
> results.put(WAIT, rc);
> //http://java.sun.com/j2se/1.4.2/docs/api/java/util/Map.html#put(java.lang.Object,%20java.lang.Object)
> }
> if (TokenHelper.getToken() != null) {
> session.put(TokenHelper.getTokenName(),
> TokenHelper.getToken());
> }
> return WAIT;
> } else if ((!executeAfterValidationPass || !secondTime) && bp !=
> null && bp.isDone()) {
> session.remove(KEY + name);
> actionInvocation.getStack().push(bp.getAction());
> // if an exception occured during action execution, throw it
> here
> if (bp.getException() != null) {
> throw bp.getException();
> }
> return bp.getResult();
> } else {
> // this is the first instance of the interceptor and there is
> no existing action
> // already run in the background, so let's just let this pass
> through. We assume
> // the action invocation will be run in the background on the
> subsequent pass through
> // this interceptor
> return actionInvocation.invoke();
> }
> }
> }
> where
> Collections.singletonMap("location",
> "/org/apache/struts2/interceptor/wait.ftl"))
> public static <K,V> Map<K,V> singletonMap(K key, V value) {
> 3343 return new SingletonMap<K,V>(key, value);
> 3344 }
> //Here is applicable SingletonMap
> 3349 private static class SingletonMap<K,V>
> 3350 extends AbstractMap<K,V>
> 3351 implements Serializable {
> 3352 private static final long serialVersionUID = -6979724477215052911L;
> 3353
> 3354 private final K k;
> 3355 private final V v;
> 3356
> 3357 SingletonMap(K key, V value) {
> 3358 k = key;
> 3359 v = value;
> 3360 }
> //UnsupportedOperation details
> The "destructive" methods contained in this interface, that is, the methods
> that modify the map on which they operate, are specified to throw
> UnsupportedOperationException if this map does not support the operation. If
> this is the case, these methods may, but are not required to, throw an
> UnsupportedOperationException if the invocation would have no effect on the
> map. For example, invoking the #putAll(Map) method on an unmodifiable map
> may, but is not required to, throw the exception if the map whose mappings
> are to be "superimposed" is empty.
> //which calls Builder
> http://struts.apache.org/2.1.6/struts2-core/apidocs/com/opensymphony/xwork2/config/entities/ResultConfig.Builder.html
> //which calls addparams method which takes 2 String placeholders for Map
> ResultConfig.Builder addParams(Map<String,String> params)
> //the code calls singletonMap which is an immutable Map
> 3332 /**
> 3333 * Returns an immutable map, mapping only the specified key to the
> 3334 * specified value. The returned map is serializable.
> 3335 *
> 3336 * @param key the sole key to be stored in the returned map.
> 3337 * @param value the value to which the returned map maps
> <tt>key</tt>.
> 3338 * @return an immutable map containing only the specified
> key-value
> 3339 * mapping.
> 3340 * @since 1.3
> 3341 */
> 3342 public static <K,V> Map<K,V> singletonMap(K key, V value) {
> 3343 return new SingletonMap<K,V>(key, value);
> 3344 }
> so the fix would be to replace
> Collections.SingletonMap
> .addParams(Collections.singletonMap("location",
> "/org/apache/struts2/interceptor/wait.ftl"))
> with 2 plain strings for addParams e.g.
> .addParams("location",
> "/org/apache/struts2/interceptor/wait.ftl"))
> ?
> Martin
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.