8

When my jsp files are inside WEB-INF folder (as /WEB-INF/file.jsp) , I can access them from localhost: 8080/ProjectCtxtRoot/, but I can't access them, if they are placed in /WEB-INF/jsp/file.jsp?

I changed the path in welcome-list tag in web.xml as follows

<welcome-file-list>
       <welcome-file>/JSP/fileName.jsp</welcome-file>
</welcome-file-list>

I also changed the dispatcher-servlet.xml as follows

   <bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" /> 

Still it doesn't work. Url used for above case are

 localhost:8080/ContextRoot/jsp/
 localhost:8080/ContextRoot/jsp/fileName.jsp
 localhost:8080/ContextRoot/jsp/fileName 

and it doesn't work for any of the above urls.

But it was working when

 <welcome-file-list>
       <welcome-file>/fileName.jsp</welcome-file>
</welcome-file-list>

dispatcher-servlet.xml as follows

<bean id="jspViewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver"
      p:prefix="/WEB-INF/"
      p:suffix=".jsp" /> 

Url used for above case is localhost:8080/ContextRoot/ and it works.

I use tomcat v 7.0 server. I refresh my project in Eclipse IDE, then clean it, build it, build war using mvn clean install, then choose the war from tomcat manager homepage and deploy it. I do this each time.

This is how the diapatcher-servlet.xml looks all through the process. I just change particular section as above said

<?xml version="1.0" encoding="UTF-8"?>


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd     
                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <mvc:annotation-driven/>

    <context:component-scan base-package="com.projectName.www" />

    <!-- Factory bean that creates the Mongo instance -->
    <bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
        <property name="host" value="localhost" />
    </bean>

    <!-- MongoTemplate for connecting and quering the documents in the database -->
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongo" ref="mongo" />
        <constructor-arg name="databaseName" value="tableName" />
    </bean>

    <!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes -->
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />



    <bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" /> 

  <!--   <bean class="org.springframework.web.servlet.view.tiles2.TilesViewResolver"/>

    <bean class=
    "org.springframework.web.servlet.view.tiles2.TilesConfigurer"> -->
 <!--  <property name="definitions">
    <list>
      <value>/WEB-INF/views/views.xml</value>
    </list>
  </property> 
</bean> -->




</beans>

This is how my web.xml looks like

<web-app>

<!--   <display-name>Archetype Created Web Application</display-name> -->

   <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/src/main/webapp/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </context-param> 

   <!--  <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener> -->

    <welcome-file-list>
       <welcome-file>/fileName.jsp</welcome-file>
    </welcome-file-list> 


</web-app>

Ok. It works when I moved the entire jsp folder from /webapp/WEB-INF/jsp/fileName.jsp to /webapp/jsp/fileName.jsp. I would like to know 1. why it works now? 2. Is this the correct way to do things? 3. It works when the url is localhost:8080/CtxtRoot/jsp/or localhost:8080/CtxtRoot/jsp/search.jsp, but it doesn't work for localhost:8080/AnnaUnivResults/jsp/search. Why is it so?

18
  • 1
    I think the capitalization might actually make a difference here, since spring is interpreting things into a file path.
    – msknapp
    Commented Sep 18, 2014 at 4:51
  • please leave a comment saying if the first example works when the welcome file has a lower case jsp.
    – msknapp
    Commented Sep 18, 2014 at 4:55
  • A <welcome-file> is completely unrelated to a Spring ViewResolver. Your question is currently all over the place. You'll have to clarify your context path and the exact HTTP request you send in each scenario. If the request is handled by Spring's DispatcherServlet, you'll need to show the handler as well. Commented Sep 18, 2014 at 5:02
  • @msknapp Making "jsp" as lower case doesn't work.
    – sofs1
    Commented Sep 18, 2014 at 5:07
  • I think you need to explain how you are running the app, the config files for your web app server might be related to some of the questions near the bottom of your post.
    – msknapp
    Commented Sep 18, 2014 at 5:11

2 Answers 2

27

I think there are a couple problems here:

  1. You are confused about the paths with spring MVC
  2. You are not configuring your web xml correctly

Unfortunately I can't cover every detail for you, a lot of spring is configurable, so my explanation is just going to cover the most basic scenario. If somebody finds a mistake please tell and I will fix it.

For the paths, it might help to think of things step by step.

  1. You request the url from your browser, The browser looks at the protocol, host, and port, and uses a DNS to find the appropriate IP address to connect with.
  2. A connection is established between your browser and the host. The host looks for a process running on the port you specified, and if a TCP connection is allowed by any security systems in place, the request is streamed to the process running on that port, the web server.
  3. The web server makes decisions based on what's after the port, specifically, it determines what the web application context is by looking at the path it was given. Once it determines the application context root, it knows which web application should handle that request. The decision is based on how you configure the web server, you could have a web application handle requests with no context root, or a specific context root. For example, if you requested localhost:8080/CtxtRoot/jsp/, you could have one web application on the server whose context root is "CtxtRoot", and it would handle that request. Alternatively, you could have an application that has "" for a context, and it could handle that request. It depends on how you configure the server, by default Tomcat will use the war name as a context root.
  4. The web application receives the request. While it knows the full URL requested, it only makes decisions based on everything after the context root. So for example, with the request to localhost:8080/CtxtRoot/jsp/, the web application would route things based on 'jsp' as the path.
  5. The web application has a filter chain that it submits the request to first. If a filter's pattern matches the request, that filter can evaluate the request. It might block the request, handle the request, or pass it on. I won't say much more because your question doesn't involve filters.
  6. The web app looks for a resource whose pattern matches the request, it considers servlets first, and then static resources. The url part that comes AFTER the context is what it tries to match, so if the request was for localhost:8080/CtxtRoot/jsp/, and the context root was 'CtxtRoot', then the web application is comparing '/jsp/' to all of the servlet mappings. Requests for static resources in WEB-INF will always be refused, but servlets and filters can and do return data from WEB-INF.
  7. I'm going to proceed assuming the request was sent to the spring DispatcherServlet, it receives the request, and considers everything after the servlet path. Spring's DispatcherServlet looks for a Controller whose path matches the path after the servlet path. The servlet path is basically what you put in the servlet mapping in your web xml. Let me give an example, let's say you have a web app whose context is 'app', and it has a spring MVC servlet whose servlet mapping is '/mvc', and a controller that handles the path 'sales', then you could reach that controller with http://localhost:8080/app/mvc/sales.
  8. If the DispatcherServlet cannot find a Controller, I believe it treats the incoming request as if it was returned by a controller, so if the sub-path is 'sales', then it would pass that as an argument to the view resolver. If it can't find it, then the server returns a not found error.
  9. Typically the Controller returns a string when it's done, which is the path to a resource. It could return 'popular' as a string. Spring then forwards this to the ViewResolver, and I will assume you're using the InternalResourceViewResolver. It will look at the prefix and suffix, and basically wrap those around what it was given. So if the prefix is '/WEB-INF/views/', the suffix is '.jsp', and the argument is 'popular', then it will look for a resource at '/WEB-INF/views/popular.jsp'. It is literally just concatenating those strings to make a path. The path is ALWAYS relative to the web application root here. If the path produced is a jsp file, it will be interpreted before being returned.
  10. Then it is finally returned to the user.

From your example you were requesting localhost:8080/ContextRoot/jsp/fileName, so it looks like 'CtxRoot' is the context root, your servlet's path is '/', so it should pass whatever is after that to a controller. By the time the DispatcherServlet receives the request, it is searching for a controller that handles 'jsp' as a path. Since you had none, it decided to treat that as a resource path. It used the view resolver and formed the path /WEB-INF/jsp/jsp/fileName.jsp, which obviously does not exist.

Let's assume that you had instead requested localhost:8080/ContextRoot/fileName, the request would reach the DispatcherServlet, it would find no Controller that handles 'fileName' as a path, and hence would treat it as a resource. It would form the path /WEB-INF/jsp/fileName.jsp, and that would return the result.

However, your web xml was not configured to initialize spring. So your web application was actually treating every one of your requests as if they were for a resource relative to the web application root. I believe that if you had made that request with Spring properly initialized, it might have worked.

Here is a good example of how to do it:

http://www.mkyong.com/spring3/spring-3-mvc-hello-world-example/

notice that his web xml has a ContextLoaderListener, which is commented out in yours, and it's essential for initializing spring in a web app. I also see the comment in your dispatcher with the path /src/main/resources, but all paths in web xml are supposed to be relative to the web application root. At runtime, the web server has no knowledge of your project, and 'src' is not a directory in your web app's root. Also note that you can have a different application context for your MVC stuff than your main spring context, and this is common.

I think if you do these things it will work:

  1. Move your jsp to /WEB-INF/jsp/fileName.jsp
  2. Update your app context so '/WEB-INF/jsp/' is the prefix, and '.jsp' is the suffix.
  3. Add the context loader listener to your web xml, and set the contextConfigLocation path relative to the app context root. For example, it could be /WEB-INF/appContext.xml
  4. make a request to

    localhost:8080/CtxtRoot/fileName

Also, you kept talking about the welcome-file, but you were giving full paths to resources. The welcome file only comes into play if the user makes a request to the root of a directory, like this:

localhost:8080/CtxtRoot/

That request would be forwarded to the welcome-file. I think the only time you tried that, the jsp happened to be in your app's root, and was configured as the welcome file, so it worked. While it "worked", it did NOT actually use spring to return that.

Good luck to you.

4
  • 1
    Dude, Thank you very much for taking effort and time in explaining this. You have ignited a Spring illiterate mind. Very well explained. I have few questions 1) Is root of a project as well as war is always '/' ? 2) How can I change the context root of an application in tomcat server? (Just out of curiosity) 3) From your overall workflow explanation, is it always a URL hits dispatcher-servlet.xml first and then it goes to web.xml? (Is this a correct statement, If not please rephrase/correct answer)
    – sofs1
    Commented Sep 20, 2014 at 7:26
  • 4) Can I use both UrlBasedViewResolver and InternalResourceViewResolver in dispatcher-servlet.xml (because I am using Apache tiles)? 5) You mentioned in point 6 "The servlet path is basically what you put in the servlet mapping in your web xml. Let me give an example, let's say you have a web app whose context is 'app', and it has a spring MVC servlet whose servlet mapping is '/mvc'.", What you mean by "spring MVC servlet whose servlet mapping is '/mvc'"? Could you please provide code for the case you were explaining /mvc.
    – sofs1
    Commented Sep 20, 2014 at 7:27
  • @msknapp I have changed the code as per your explanation. But still I am facing problems in fixing it. When you were writing the answer, I also brought in tiles feature into the project. Here is the new question stackoverflow.com/questions/25947668/… Please help(teach) me. You are the only one who is clarify my questions now. Thanks a ton.
    – sofs1
    Commented Sep 20, 2014 at 18:41
  • This is what explanations should look like -- msknapp clearly has both knowledge and understanding of the topic; not just what to do, but how it works. A problem with the industry's obsession with examples as documentation is that it doesn't have enough explanation about how things work, as opposed to just "do this, and that happens".
    – arcy
    Commented Sep 15, 2016 at 19:20
-3

Everything outside WEB-INF is publicly available no authentication is applied on that(we can apply by defining scurity constraint in web.xml ), but all resources inside WEB-INF is secured. You can keep static pages outside WEB-INF and dynamic pages like profiles, accounts inside WEB-INF. Please cross check i might be wrong.

2
  • normally you would be right, but since he is using Spring MVC, spring is able to show jsp files inside web-inf, and it's actually done a lot in their examples. Spring has a filter that intercepts the request, and determines where to get the view from. His view resolver is configured to get it from within web-inf, which is perfectly fine since the access is coming through the filter, in other words, not accessed directly by http request.
    – msknapp
    Commented Sep 18, 2014 at 4:51
  • OP hasn't accessed anything outside of WEB-INF. Commented Sep 18, 2014 at 4:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.