Thursday, October 7, 2010

Redirecting 404 error if users type in invalid URL which starts with /wps/portal

As a default behavior in portal 6.1.x, if a user type in a url, which starts in /wps/portal/*, in a browser's window, the portal server will automatically redirect user to the first available anonymous page in portal. The example of the URL includes: http://<serveraddress>/wps/portal/invalidpage. Sometimes this behavior is not acceptable by some portal users, the requirements is to let the user knows that the page does not exist or no longer exist.

In order to change this behavior we need to intercept the http status code 404, and modify the default redirection to redirect to a specified page. The best way to do that is to write a servlet filter and a wrapper for the servlet response.

  • The servlet filter:
    package com.servletFilter;

    import javax.servlet.Filter;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletResponse;


    /**
     *
     * This is the servlet filter that wrap the servlet response object
     * and use it in the FilterChain
     * The wrapper will store the status code and do the re-direct if necessary
     */
    public class Redirect404 implements Filter {
      

        public void destroy() {
            // TODO Auto-generated method stub

        }

        public void doFilter(javax.servlet.ServletRequest request, 
                  javax.servlet.ServletResponse response,
                  javax.servlet.FilterChain chain)
              throws java.io.IOException, javax.servlet.ServletException{

            HttpStatusServletResponse statusResponse =
                new HttpStatusServletResponse((HttpServletResponse) response);
            chain.doFilter(request, statusResponse);
            int status = statusResponse.getStatus();
            System.out.println("******** Status: " + status);
        }   

        public void init(FilterConfig arg0) throws ServletException {
           
        }
    }
     

    •  The servlet response wrapper
    package com.servletFilter;

    import java.io.IOException;

    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;

    /**
     *
     * This is a wrapper class which is used to store the HTTP Status Code and modify the redirect.
     * 
     */
    public class HttpStatusServletResponse extends HttpServletResponseWrapper {

        private int httpStatus;

        public HttpStatusServletResponse(HttpServletResponse response) {
            super(response);
        }

        @Override
        public void sendError(int sc) throws IOException {
            httpStatus = sc;
                super.sendError(sc);
        }

        @Override
        public void sendError(int sc, String msg) throws IOException {
            httpStatus = sc;
                super.sendError(sc, msg);
        }

        @Override
        public void sendRedirect(String location) throws IOException {
            System.out.println("******* Calling sendRedirect, location is: " + location);
            if (httpStatus == SC_NOT_FOUND)
                location = "/wps/portal/404Error";
            super.sendRedirect(location);
        }

        @Override
        public void setStatus(int sc) {
            httpStatus = sc;
            super.setStatus(sc);
        }

        @Override
        public void flushBuffer() throws java.io.IOException {
                super.flushBuffer();
        }
       
        public int getStatus() {
            return httpStatus;
        }

    }

      We need to place these class files in a place the classpath of WebSphere Portal server. I placed it in: <portal_root>/shared/ext.

      We also need to modify the web.xml of wps.war, to add the filter definition and filter mapping. The following is the definition:
          <filter>
              <filter-name>Error 404 Redirect</filter-name>
              <filter-class>com.servletFilter.Redirect404</filter-class>
          </filter>
          <filter-mapping>
              <filter-name>Error 404 Redirect</filter-name>
              <url-pattern>/portal/*</url-pattern>
          </filter-mapping>



      To update web.xml, you will need to export wps.ear (using wsadmin.sh|bat), expand wps.ear (using EARExpander.sh|bat), update web.xml (located at wps.war/WEB-INF), collapse back the wps.ear (using EARExpander.sh|bat), and install the new wps.ear back to portal server (using wsadmin.sh).  The detailed instruction can be found in the following reference: How to redirect to a custom error page when HTTP 404 Not Found encountered on Non-URL Resources ("Resolving the problem" section).


      References: