You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.
In some instances you need to do a redirect to a URL outside your application, for example when a given page is widely linked by external sites and is moved to another application, or on SEO situations that require a 301.
package com.boulevardr.ui;
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
@Name("permanentRedirector") public class PermanentRedirector
{
@In FacesContext facesContext;
public void toUrl(String location)
{
HttpServletResponse res = (HttpServletResponse)facesContext.getExternalContext().getResponse();
res.setContentType("text/html");
res.setHeader("Location", location);
res.setStatus(301);
facesContext.responseComplete();
}
}
on pages.xml:
<page view-id="/page.seam" action="#{permanentRedirector.toUrl('http://site.to.redirect')}" />
It was suggested that this kind of redirect should be done in a Servlet. However, I prefer to keep all flow-related rules on a single location (i. e.: pages.xml), and that was my main motivation behind this solution.
The above solution does require you to construct absolute URLs and prevents you from using the Seam Redirect component.
Here's my solution. To enable a 301 redirect call the following:
before the code you use your normal code to redirect
Here is the redirector class:
package com.example; import org.jboss.seam.annotations.Install; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.intercept.BypassInterceptors; import org.jboss.seam.annotations.web.Filter; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.web.AbstractFilter; import javax.faces.context.FacesContext; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import static org.jboss.seam.ScopeType.APPLICATION; import static org.jboss.seam.annotations.Install.BUILT_IN; @Scope(APPLICATION) @Name("permenantRedirectFilter") @Install(precedence = BUILT_IN, classDependencies = "javax.faces.context.FacesContext") @BypassInterceptors @Filter(within = "org.jboss.seam.web.ajax4jsfFilter", around = "org.jboss.seam.web.redirectFilter") public class PermenantRedirectFilter extends AbstractFilter { public static final String REDIRECT_301 = "REDIRECT_301"; public static void redirect301() { if (Contexts.isEventContextActive()) { Contexts.getEventContext().set(REDIRECT_301, true); } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, wrapResponse((HttpServletResponse) response)); } private static ServletResponse wrapResponse(HttpServletResponse response) { return new HttpServletResponseWrapper(response) { @Override public void sendRedirect(String location) throws IOException { if (FacesContext.getCurrentInstance() != null && Contexts.isEventContextActive() && Contexts.getEventContext().isSet(REDIRECT_301)) { setHeader("Location", toAbsolute(location)); setStatus(SC_MOVED_PERMANENTLY); } else { super.sendRedirect(location); } } protected String toAbsolute(String location) { if (location == null) location = "/"; if (!location.startsWith("http://") && !location.startsWith("https://")) { try { StringBuilder sb = new StringBuilder(); URL reqUrl = new URL(getRequestUrl(FacesContext.getCurrentInstance())); sb.append(reqUrl.getProtocol()); sb.append("://"); sb.append(reqUrl.getHost()); if (("http".equals(reqUrl.getProtocol()) && (reqUrl.getPort() != -1 && reqUrl.getPort() != 80)) || ("https".equals(reqUrl.getProtocol()) && (reqUrl.getPort() != -1 && reqUrl.getPort() != 443))){ sb.append(':').append(reqUrl.getPort()); } if (!location.startsWith("/")){ sb.append('/'); } sb.append(location); location = sb.toString(); } catch (MalformedURLException e){ } } return location; } protected String getRequestUrl(FacesContext facesContext) { Object request = facesContext.getExternalContext().getRequest(); if (request instanceof HttpServletRequest) { return ((HttpServletRequest) request).getRequestURL().toString(); } else { return null; } } }; } }The only caveat is that I took a shortcut and ignored the httpPort and httpsPort from Pages. This could be integrated fairly easily. Could probably be tidied a little too!