Redirect after Response has been written in Wicket 7.10

445 views Asked by At

We having a specific problem in using Wicket 7.10, creating an Ajax-Response with multiple entries.

In our application, we are using onRequestHandlerResolved to do some initialization stuff and onRequestHandlerExecuted to save changes done on our data during requestHandlerExecutor.execute(). For this purpose, we have created an own AbstractRequestCycleListener which overwrites both methods and calls our specific code.

RequestCycle:

private void execute(IRequestHandler handler)
{
  try
  {
    listeners.onRequestHandlerResolved(this, handler);
    requestHandlerExecutor.execute(handler);
    listeners.onRequestHandlerExecuted(this, handler);
  }
  catch (RuntimeException e)
  {
  }
}

Our problem is, that an Exception thrown in onRequestHandlerExecuted after requestHandlerExecutor.execute() has already created an ajax-response creates an invalid response:

Wicket.Ajax:  Wicket.Ajax.Call.failure: Error while parsing response: Error: Invalid XML: 
<?xml version="1.0" encoding="UTF-8"?>
<ajax-response>
  <!-- Result of requestHandlerExecutor.execute()  -->
</ajax-response>
<ajax-response>
  <!—Redirect to specific Exception Page, result of onRequestHandlerExecuted -->
  <redirect>
    <![CDATA[./wicket/bookmarkable/our.package.ExceptionPage?locale=en]]>
  </redirect>
</ajax-response>

To solve our problem, we tried to clear the existing Response during Exception in onRequestHandlerExecuted (RequestCycle.get().getResponse().reset()), but we are not able to clear the Response, created in requestHandlerExecutor.execute(), because Wicket uses HeaderBufferingWebResponse by default which did not allow to reset already created Response in encapsulated ServletWebResponse. Calling reset in HeaderBufferingWebResponse instead throws an IllegalStateException.

We think that the problem came from ServletWebResponse which simply adds multiple ajax-response entries to the HttpServletResponse which results in the mentioned, invalid XML.

ServletWebResponse:

@Override
public void sendRedirect(String url)
{
 try
 {
  if (webRequest.isAjax())
  {
   /*
    * usually the Ajax-Location header is enough and we do not need to the redirect url
    * into the response, but sometimes the response is processed via an iframe (eg
    * using multipart ajax handling) and the headers are not available because XHR is
    * not used and that is the only way javascript has access to response headers.
    */
   httpServletResponse.getWriter().write(
    "<ajax-response><redirect><![CDATA[" + url + "]]></redirect></ajax-response>");
  }
  else { }
 }
 catch (IOException e) {  }
}

How we could handle the problem when throwing an Exception in onRequestHandlerExecuted? And how is it possible, that code run after requestHandlerExecutor.execute(), redirects correctly to an Exception page? How we can run specific code, after the request has been processed, is there maybe another way instead of overwriting onRequestHandlerExecuted?

1

There are 1 answers

0
svenmeier On

For each Ajax request Wicket executes two request handlers:

  • ListenerInterfaceRequestHandler
  • AjaxRequestHandler

I assume your #onRequestHandlerExecuted is failing after the second one. This might be too late since the response is already generated and written.

You could check:

  • why does your listener fail after anything else has happened already?
  • what do you want your application to do when your listener fails?
  • can't the listener fail after the first handler already? why wait any longer?