[ https://issues.apache.org/struts/browse/WW-3068?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=45813#action_45813 ]
Musachy Barroso commented on WW-3068: ------------------------------------- The problem is that configuration is now unmodifiable, so adding a "fake" result to the result config map will cause an exception to be thrown. > 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 > > 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.