1

I'm trying to map a request for a "fake" MSWord file: the file is an html page actually, with a .doc extension to force the user to download it and open it with MS Word.

The source file /app/report.jsp is populated and shown as an HTML page if the mapped URL does not contains a .doc extension, but if I add the extension all the <jsp:include /> in the jsp file stop working, and at the same time the file is still rendered as a html document.

How can I force the user to download the file as a Word document?

Here is the method mapping the URL, from my controller:

@RequestMapping(value="/report.doc", produces = "application/msword")
    public ModelAndView reportProducer(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mav = new ModelAndView();
        mav.addObject("something", false);
        mav.setViewName("/app/report");
        response.setContentType("application/msword"); // probably unnecessary?
        return mav;
    }

here is the web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:mvc="http://www.springframework.org/schema/mvc"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
     id="WebApp_ID" version="3.1">

<display-name>MyApp</display-name>

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

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

<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/classes/jsp/app/errorPage.jsp</location>
</error-page>

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </init-param>
</servlet>

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

</web-app>

and here is my applicationContext.xml file:

<?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:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<mvc:annotation-driven/>
<mvc:view-controller path="/" view-name="home"/>

<context:annotation-config/>
<context:component-scan base-package="myBasePackage1, myBasePackage2"/>

[... datasources, beans omitted ...]

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/classes/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

</beans>


EDIT

The issue with the incomplete parsing of the page (not including *.jspf parts) is related to a change I did while trying to solve the issue. I removed the following code from web.xml. When restored, everything worked as expected:

<servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>*.jspf</url-pattern>
    <url-pattern>*.jsp</url-pattern>
</servlet-mapping>
7
  • If you're returning a view name, you're expecting the contents of the corresponding JSP to be the entire response. Commented Dec 15, 2016 at 19:09
  • 1
    I don't understand how JSP includes could fail just because the request has been forwarded from a controller mapped to a .doc URL. What is the code of the JSP? The JSP should have <%@ page contentType="application/msword" %> Commented Dec 15, 2016 at 19:13
  • @SotiriosDelimanolis Indeed, I expect the corresponding JSP to be the entire response. The "includes" does not get included, unfortunately, but only if there is a ".doc" extension in the RequestMapping annotation value Commented Dec 15, 2016 at 19:20
  • @JBNizet you are correct, if the page contentType is "application/msword" the page became a downloadable file, and word opens it correctly. It's difficult to provide you the entire page/includes because of their size, but I can say that all the JSTL/EL code get rendered correctly, only <jsp:include page="/WEB-INF/classes/jspf/report/details.jspf"/> -like code does not get parsed if the file extension is .doc. This is weird. Commented Dec 15, 2016 at 19:50
  • @JBNizet BTW you answered to my main question, so if you'd like to add an answer I'd be glad to accept it :) Commented Dec 15, 2016 at 19:52

1 Answer 1

1

jspf files are normally JSP fragments, that are supposed to be included statically, not dynamically. I wouldn't use that standard file extension for regular JSPs. Just use the .jsp extension. That would make your custom jsp servlet mapping unnecessary, and would be less confusing.

WEB-INF/classes is for classes and resources loaded by the class loader. JSPs shouldn't be located there. I would put them anywhere else under WEB-INF.

Finally, regarding the rendering as a web page, that is because the default content type set by JSPs is text/html. You need to add

<%@ page contentType="application/msword" %>

at the top of your JSP to set the appropriate content type.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.