It took me a while to get welcome files working with the SpringMVC web 
framework.

I created the attached servlet to get things working properly.  It requires 
servlet spec 2.4, and it works by mapping the welcome file to a servlet, 
WelcomeFileServlet, rather than direct to a JSP.  The WelcomeFileServlet then 
forwards it on to the correct servlet, and makes sure that the requestURI 
returns the right value (e.g. /index.htm rather than just /) It should work 
fine with JSF, if you configure it properly.

Here's an example of how to configure it in web.xml

        <servlet>
                <servlet-name>WelcomeFileServlet</servlet-name>
                
<servlet-class>com.mbromley.util.servlet.WelcomeFileServlet</servlet-class>
                <init-param>
                        <param-name>forward-to-servlet-name</param-name>
                        <param-value>DispatcherServlet</param-value>
                </init-param>
                <init-param>
                        <param-name>welcome-file</param-name>
                        <param-value>index.htm</param-value>
                </init-param>
        </servlet>

It works by mapping the index page (index.htm in my case, index.faces or 
whatever in yours) to the WelcomeFileServlet:
        
        <!-- Exact mappings are needed below for the welcome-file feature to work 
with WelcomeFileServlet. -->
        <servlet-mapping>
                <servlet-name>WelcomeFileServlet</servlet-name>
                <url-pattern>/index.htm</url-pattern>
        </servlet-mapping>

and then defining the welcome file as
<!-- This relies on the 2.4 spec allowing mappings to a servlet as opposed to just 
a real file (index.htm doesn't exist as a real file in any of the directories this 
feature is required).  The WelcomeFileServlet docs have lots of info on the correct 
setup of that class. -->
        <welcome-file-list>
                <welcome-file>index.htm</welcome-file>
        </welcome-file-list>

Take a look at the docs with the attached file for more.

Hope it helps,

Martin with an 'i' ;-)




Marten Lehmann wrote:
Hello,

I tried to put the following into web.xml:

<welcome-file-list>
    <welcome-file>index.faces</welcome-file>
</welcome-file-list>

But obviously, this doesn't work, because there is no file index.faces, but index.jsp. However, if the index.jsp isn't called through index.faces, the FacesContext isn't used. How can I achieve this as expected? I don't want to use the plain old workaround with an index.html containing a refresh.

Regards
Marten

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

package com.mbromley.util.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/** This enables the URLs in an HttpServletRequest to be consistently rewritten.
 * This needs to be extended for it to do anything useful.  At least one of the
 * rewriteURL methods needs to be overridden.
 */
public abstract class URLRewritingRequestWrapper 
                extends HttpServletRequestWrapper {
        
        public URLRewritingRequestWrapper(
                        final HttpServletRequest request) {
                super(request);
        }
        
        @Override
        public final String getPathInfo() {
                return getPossiblyNull(super.getPathInfo());
        }
        
        @Override
        public final String getPathTranslated() {
                return getPossiblyNull(super.getPathTranslated());
        }
        
        @Override
        public final String getRequestURI() {
                return rewriteURL(super.getRequestURI());
        }
        
        @Override
        public final StringBuffer getRequestURL() {
                return rewriteURL(super.getRequestURL());
        }
        
        @Override
        public final String getServletPath() {
                return rewriteURL(super.getServletPath());
        }
        
        private String getPossiblyNull(final String s) {
                if (s == null) {
                        return null;
                }
                return rewriteURL(s);
        }
        
        /** Subclasses can override this if they can improve efficiency by 
rewriting
         * a StringBuffer.  By default this calls the other method and creates 
a new
         * StringBuffer from the result.
         */
        protected StringBuffer rewriteURL(final StringBuffer sB) {
                return new StringBuffer(rewriteURL(sB.toString()));
        }
        
        protected abstract String rewriteURL(final String url);
        
        @Override
        public String toString() {
                return super.toString() + " wrapping " + 
getRequest().toString();
        }
        
}
package com.mbromley.util.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/** <p>Enables welcome-file configuration in web.xml to work with frameworks 
 * such as SpringMVC (and presumably Struts).</p>
 * 
 * <p>welcome-file enables an application to configure default files that are
 * accessed when somebody enters a URL such as www.domain.com/.  It can be 
 * difficult to integrate this functionality with an MVC framework such as 
 * SpringMVC.  The following are issues that complicate matters:</p>
 * 
 * <ul>
 * <li>welcome-file configuration is allowed to occur in a number of ways
 * according to the servlet spec.  "The container may send the request 
 * to the welcome resource with a forward, a redirect, or a container specific 
 * mechanism that is indistinguishable from a direct request."</li>
 * 
 * <li>If there isn't a redirect, the ServletRequest can have the wrong 
 * parameters in its methods such as getRequestURI - this means that the e.g.
 * DispatcherServlet can't figure out which page it's supposed to send the 
 * request.  Tomcat certainly has this issue.</li>
 * 
 * <li>Since servlet 2.4, a welcome-file is allowed to send to a servlet as well
 * as a file (which is good).  "The Web server must append each welcome file in 
 * the order specified in the deployment descriptor to the partial request and 
 * check whether a static resource or servlet in the WAR is mapped to that 
 * request URI."</li>
 * 
 * <li>Testing with Tomcat 5.7 reveals that a map to a servlet occurs whether or
 * not the servlet-mapping is an exact match (e.g. "/index.htm", or "/index", or
 * "*.htm").</li>
 * 
 * <li>So, if the welcome-file is listed as index.htm, and the SpringMVC
 * DispatcherServlet (or equivalent) is matched to *.htm, the request will get
 * routed there (or redirected).  Explicit mappings would have to be made in
 * SpringMVC to deal with a / request - if the welcome file has to be dealt with
 * as an explicit case it's probably better to deal with it outside of SpringMVC
 * so that any framework can handle it.</li>
 * 
 * <li>It is possible to use a jsp file that forwards to the required URL 
 * (e.g. index.htm) that will reach the MVC controller servlet.  However,
 * the problem with that is that an MVC app would usually be set up to block
 * direct access to *.jsp: because the welcome-file can happen with a redirect,
 * it wouldn't be possible to block all jsp files (e.g. start.jsp, which would
 * do the forwarding would have to be specified elsewhere).  In Tomcat, for 
 * example, a filter set up to block access to all JSP files stops a 
 * welcome-file of start.jsp from working.  This also means that the server 
 * would no longer be platform agnostic in the urls it exposed.
 * This is especially concerning if a container redirected to start.jsp: a user
 * might bookmark that implementation detail of the site.</li>
 * 
 * <li>Tomcat web.xml defines default welcome-files that it looks for.  They
 * have no effect if the context web.xml defines a welcome-file-list.</li>
 * </ul>
 * 
 * <li>Using a url-pattern of / to map to a specific servlet (for Tomcat this
 * required getting rid of the welcome-file-list in the Tomcat web.xml, and not 
 * putting one in the web.xml of the context) appears to cause problems in 
 * different containers.  In Tomcat it certainly seemed to cause problems, 
 * although it seemed to work in the base directory.
 * See <a href="http://forum.java.sun.com/thread.jspa?ageID=1131960";>this
 * thread</a> for problems with other containers.</li>
 * 
 * <li>There was a 
 * <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=9016";>bug in 
 * Tomcat</a> that meant that a real file had to exist for the welcome-file 
 * mapping to a servlet to work, but that was fixed in version 5.  A hack was
 * to create an empty real file (e.g. index.htm) for every directory in which 
 * the welcome file was supposed to work.</li>
 * 
 * <p>This simple servlet offers a solution that works with Servlet 2.4+.  It
 * simply forwards onto another named servlet (specified in an init-parameter),
 * and wraps the request so that any Url related methods ending in a "/" have
 * the welcome-file appended to them (the welcome-file is specified in another
 * init parameter).</p>
 * 
 * <p>Guidance notes:</p>
 * 
 * <ul>
 * <li>web.xml must should contain a welcome-file (e.g. index.htm).</li>
 * 
 * <li>The welcome-file init parameter to this servlet should be the same.</li>
 * 
 * <li>An exact servlet-mapping should be made to every url for which this
 * welcome-file is expected to work.  For example, one to "/index.htm", one to
 * "/user/index.htm" etc.</li>
 * </ul>
 * 
 * @author Martin Bromley
 *
 */
public class WelcomeFileServlet extends HttpServlet {
        
        private static final long serialVersionUID = 3761410819778163249L;
        
        public static final String FORWARD_TO_SERVLET_NAME_INIT_PARAMETER =
                "forward-to-servlet-name";
        public static final String WELCOME_FILE_INIT_PARAMETER = "welcome-file";
        
        private RequestDispatcher requestDispatcher;
        private String welcomeFile;
        
        @Override
        public void init() throws ServletException {
                final String servletName = 
                        
getInitParameter(FORWARD_TO_SERVLET_NAME_INIT_PARAMETER);
                if (servletName == null) {
                        throw new ServletException("Init parameter "
                                + FORWARD_TO_SERVLET_NAME_INIT_PARAMETER + " 
not specified. "
                                + "This servlet needs to forward onto another 
one.");
                }
                requestDispatcher = 
getServletContext().getNamedDispatcher(servletName);
                if (requestDispatcher == null) {
                        throw new ServletException("RequestDispatcher could not 
be "
                                + "found with the name specified in the "
                                + FORWARD_TO_SERVLET_NAME_INIT_PARAMETER + " 
init parameter: "
                                + servletName);
                }
                welcomeFile = getInitParameter("welcome-file");
                if (welcomeFile == null) {
                        throw new ServletException("The init parameter " 
                                + WELCOME_FILE_INIT_PARAMETER + " is 
required.");
                }
        }
        
        @Override
        protected void doGet(final HttpServletRequest request, 
                        final HttpServletResponse response) 
                                throws ServletException, IOException {
                requestDispatcher.forward(new RequestWrapper(request), 
response);
        }
        
        private class RequestWrapper extends URLRewritingRequestWrapper {
                RequestWrapper(final HttpServletRequest request) {
                        super(request);
                }
                @Override
                protected String rewriteURL(final String url) {
                        if (url.endsWith("/")) {
                                return url + welcomeFile;
                        } else {
                                return url;
                        }
                }
        }

}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to