Spring:url not resolving links correctly

18,545

Solution 1

It is good practice to put all your links as follows

<a href="${pageContext.servletContext.contextPath}/othersite"> Other site </a>

${pageContext.servletContext.contextPath} always gives your application root, when you are developing use http://localhost:8080/myApp, then your application root is /myapp, but when you want to place your application in production generally your application root will be /, using ${pageContext.servletContext.contextPath} before links you ensure it will work in both cases

Solution 2

When facing same problem I use c liblary:

 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

 <a href="<c:url value="/otherSite"/>"> Other site </a> 

Solution 3

This should do the trick:

<spring:url value="/some_link" context="myApp" var="apps_url" />
<a href="${apps_url}">link</a>

apps_url should be equal to: http://localhost:8080/myApp/some_link

Solution 4

Tomcat can have many web apps executing at the same time. Consider the scenario:

  • tomcat is running on 8080
  • tomcat web apps folder has three apps running in it
    • appA.war
    • appB.war
    • ROOT.war

The URL http://localhost:8080/ will be get the request to tomcat and tomcat must decide which of three apps should service the request since the URL does not identify the app the request will be routed by tomcat to the ROOT.war which is the root web app in tomcat.

When you have a JSP in appA.war with <a href="/otherSite">link</a> in it then the web browser that parses the output will figure that the request should be submitted to root of the server since the href started with / therefore the browser puts togethec the url http://localhost:8080/otherSite when the request get to tomcat tomcat assumes that /otherSite is refering to a web app called otherSite.war but of course that is not there.

if you use <a href="otherSite">link</a> the browser will assume this is a relative URL and so it will send the request to http://localhost:8080/appA/otherSite because the page that generate the url was served out of the context http://localhost:8080/appA

So in general you need to make sure that the URLs from a JSP page are relative or that you add the context name to the generated url, this is what <spring:url /> and <c:url /> tags do.

is there any connection between the url on local tomcat server and the url the webapplication will have when its published?

the URL for the context is the same as the name of the war file in the tomcat webapps folder unless you change that in the server.xml or in the context.xml file.

Share:
18,545
jeyp
Author by

jeyp

Updated on June 26, 2022

Comments

  • jeyp
    jeyp almost 2 years

    I'm pretty new to the Spring framework and web applications, though I'm experienced with Java. When I run my site on a local tomcat server the URL is: http://localhost:8080/myApp/

    Now a request mapping delegates me to my home page with:

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String someMethod(Model model) { ... 
       return "index"; }
    

    Now within a file index.xhtml I link to another page with <a href="apps/">link</a> but when I want to link back to the index page I have to use <a href="../index/">link</a>. I searched for a solution and found:

    <spring:url value='/apps' var="apps_url" />
    <a href="${apps_url}">link</a>
    

    But spring:url always resolves to http://localhost:8080/myApp/ - the page that I'm currently on. In addition, when I just use a link like this: <a href="/otherSite">link</a>, it always resolves to http://localhost:8080/otherSite and not http://localhost:8080/myApp/otherSite like I expected. How can I get my link to work? Is http://localhost:8080/myApp implicitly defined as my context or can/should it be changed to http://localhost:8080/?

    Also, is there any connection between the URL on local tomcat server and the URL the web application will have when it's published?

    Here are some of my application files:

    servlet-context.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/mvc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:beans="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
        <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
        <!-- Enables the Spring MVC @Controller programming model -->
        <annotation-driven />
    
        <context:component-scan base-package="myApp" />
    
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
        <!-- Handles HTTP GET requests for /resources/** and /css/** by efficiently 
        serving up static resources in the ${webappRoot}/resources directory -->
        <resources mapping="/resources/**" location="/resources/" />
        <resources mapping="/css/**" location="/css/" />
    
        <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <beans:property name="prefix" value="/WEB-INF/views/" />
            <beans:property name="suffix" value=".xhtml" />
        </beans:bean>
    
    </beans:beans>
    

    excerpt from web.xml:

    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml</param-value>
    </context-param>
    
    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- Processes application requests -->
    
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>