Michael Edge wrote:

> It seems to me that the following code will not work in Cocoon 2. 
> I believe it works in Cocoon 1, but for some reason the request
> and response objects available within XSP for Cocoon 2 are not
> HttpServletRequest and HttpServletResponse objects, but rather
> some cocoon equivalents, org.apache.cocoon.environment.Response
> and org.apache.cocoon.environment.Request. Unfortunately these
> new classes do not include the sendRedirect method. Any ideas
> how I would do this? I need to construct a URL in my code
> and redirect to that URL.

  <xsp:logic>
    String url = URLEncoder.encode(url + whatever + parameters);
    response.sendRedirect(url);
  </xsp:logic>

Reply:

Don't use XSPs for flow control, use the sitemap. This is a common error with new users, that forget that it's the sitemap that manages the relations between pages.

If it's in the pages, the "flow" logic is dispersed; in the Cocoon sitemap it's easier to see, manage and change.

Even more so, sending a HTTP redirect works only reliably before any content has been delivered to the client. Because of Cocoon's pipeline model this is almost impossible to do from a XSP.

Add an Action that does this and redirect. You can write XSPAction BTW.

Better still, use the action to return the url and then do a <Redirects> in the sitemap; it makes your action more reusable.


Another reply:

I wanted to redirect according to a URL provided in one of the XML documents being processed; something like this:

  <map:match pattern="my-resource">
    ...
    <map:transform type="special-transformer"/>
    <map:redirect-to uri="{request-attr:my-parameter}"/>
  </map:match>

Here, the "special-transformer" would be based on AbstractDOMTransformer and set request attributes when it saw various things in the document. Unfortunately, the redirect is "precalculated" and the desired value for "my-parameter" never gets used.

So what I did instead was to use some arguably nasty code in my "special-transformer" to set the redirect:

import org.apache.cocoon.environment.Response;
import org.apache.cocoon.environment.http.HttpResponse;

  // ...

  if (response instanceof HttpResponse) {
    ((HttpResponse) response).sendPermanentRedirect(target);
  }

This isn't nice, but there really doesn't seem to be any sane way in "vanilla" Cocoon where sitemap actions can be influenced by the content being processed. I don't want to use FlowScript, XSP or any of the peripherals.


Yet another reply:

The redirect attempted by the previous reply can be done using the cinclude transformer. In your pipeline, this looks like:

        <map:transform src="redirect-include.xsl">
          <map:parameter name="uri" value="{request-attr:my-parameter}"/>
        </map:transform>
        <map:transform type="cinclude"/>

The stylesheet 'redirect-include.xsl' is simply:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <xsl:param name="uri"/>

  <xsl:template match="/">
    <ci:include src="{$uri}" xmlns:ci="http://apache.org/cocoon/include/1.0"/>
  </xsl:template>

</xsl:stylesheet>

After cinclude has done its work, the rest of the original pipeline is executed, so you will need at least a serializer after cinclude.

  • No labels