Spring MVC XML result chunked, missing Content-length header - spring

I have a bunch of web services that return some content, sometimes > 100kb.
Unfortunately for the bigger results, I get the partial response with Transfer-encoding: Chunked.
Is there any way to disable chunking?
That's my method:
#RequestMapping(value = "/form/{repository}/{objectId}", method = RequestMethod.GET, headers="()")
#ResponseBody
public FormHelper getFormConfig(HttpServletRequest req, HttpServletResponse resp, #PathVariable String repository,
#PathVariable("objectId") String objectId) throws Exception
And that's the Spring XML config:
<import resource="classpath*:context-aaa.xml" />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="useDefaultSuffixPattern" value="false" />
</bean>
I had the same issue with Jersey library so I rewrote the project into Spring MVC, but it's still there...
Thanks in advance for any help.
Mariusz

I was able to make that work by adding the filter below:
<filter>
<filter-name>bufferFilter</filter-name>
<filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>bufferFilter</filter-name>
<url-pattern>/services/*</url-pattern>
</filter-mapping>
https://jira.spring.io/browse/SPR-11948

Related

Set custom response in Spring interceptor

Here is my interceptor method where i want to set custom response to tell the UI what happened
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession(false);
if (session != null)
return true;
else{
response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT)
return false;
}
}
And in web.xml
<error-page>
<error-code>408</error-code>
<location>/error.html</location>
</error-page>
spring-servlet.xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/login" />
<bean class="com.example.CustomInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
When the session is timed out its not sending any response after return false.
Even the below is not working
response.sendRedirect("http://localhost:8080/home");
You can try very simple thing. Change your mvc:interceptros structure to
<mvc:interceptors>
<bean class="com.example.CustomInterceptor" />
</mvc:interceptors>
This essentially mean apply the interceptor to all applicable requests. I will come in a moment to why I say applicable in a moment. If above works then the issue is with your mapping.
Now as you know interceptors are configured at the level of HandlerMapping and it will be RequestMappingHandlerMapping (Spring 3.1+ with mvc:annotation-driven) or DefaultAnnotationHandlerMapping in your case.
Now as you have use <mvc:mapping path="/**" /> will map to all requests (including subpaths) as long as they are valid mappings. So lets say you have controller
#RequestMapping(value="/home", method = RequestMethod.GET)
public String welcome() {
return "welcome";
}
you cannot hit http://localhost:8080/yourProjectName/home/test and expect it to hit the interceptor. So you have to hit http://localhost:8080/yourProjectName/home as that is a valid HandlerMapping.
As to to response first debug if your interceptor is getting hit for any requests. If it does work then
response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT);
should redirect you to error.html as you have used
<error-page>
<error-code>408</error-code>
<location>/error.html</location>
</error-page>

Spring Boot UTF-8 encoding issue. I suspect it tries to encode ISO-8859-1 to UTF-8

I'd like to use UTF-8 character encoding but I read somewhere that the controller's default encoding's ISO-8859-1.
I'm using spring boot with velocity.
So what I did, I tried to add the following ones (one at a time) to the header (None of them worked.)
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
Plus added to the application.properties the following lines:
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.velocity.charset=UTF-8
spring.velocity.content-type=text/html
server.tomcat.uri-encoding = UTF-8
I even tried to add the following line to the controller:
#RequestMapping(value = "/", method = RequestMethod.GET, produces={"text/html; charset=UTF-8"})
Plus tried to add the following bean to the application class:
#Bean
public HttpMessageConverter<String> responseBodyConverter() {
HttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
return converter;
}
This's a sample text that I included in the velocity template:
A sötét lovag igazi főhőse azonban valahogy ezúttal mégsem a mostanság nőnemű családtagjait szállodaszobábkban riogató Christian Bale, azaz a denevérember lett - hanem az ellenfél.
And that's the output I get:
A sötét lovag igazi fÅhÅse azonban valahogy ezúttal mégsem a mostanság nÅnemű családtagjait szállodaszobábkban riogató Christian Bale, azaz a denevérember lett - hanem az ellenfél.
Edit:
This's the controller I'm using currently:
#RequestMapping(value = "/", method = RequestMethod.GET, produces={"text/html; charset=UTF-8"})
public String homepage(Map<String, Object> model) {
return "homepage";
}
And I have a homepage.vm file at templates. Which has a header partial that contains this line:
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
Could be due to default Eclipse encoding?
Window -> Preferences -> General -> Workspace : Text file encoding
To resolve same problem, I have used VelocityConfigurer with the following bean definition:
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/pages/"/>
<property name="configLocation" value="/WEB-INF/velocity.properties"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="false"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
<property name="contentType" value="text/html; charset=UTF-8"/>
</bean>
Please note the contentType property set in viewResolver.
When first tried providing it via VelocityEngineFactoryBean, I have realised late that my properties file was ignored.
Also, in velocity.properties make sure you have:
input.encoding=utf-8
output.encoding=utf-8
I didn't need anything else in here for simple case.
In web.xml:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
That was it, I had no use for "produces" attribute in controller, no http meta needed, no xml charset encoding specified in the template file and no messing with messageconverter.
EDIT:
I don't have a playground setup with Spring Boot so can't test the exact implementation for you right now. However, web.xml here only defines a filter which can also be achieved programatically with Spring Boot:
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
#Component
public class MyFilter implements Filter {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//action here
filterChain.doFilter(servletRequest, servletResponse);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void destroy() {}
}
I believe Spring Boot scans the sources for #Component automatically, otherwise package with filter's implementation should be added to component scan.
As for ideas on what the filter should do within doFilter(), you could explore the source code of Spring's CharacterEncodingFilter: https://github.com/spring-projects/spring-framework/blob/v4.2.1.RELEASE/spring-web/src/main/java/org/springframework/web/filter/CharacterEncodingFilter.java
Note that the above filter already extends other classes (such as OncePerRequestFilter).
I suppose you could instead add a method returning the filter instance:
#Bean
public Filter getCharacterEncodingFilter() {
org.springframework.web.filter.CharacterEncodingFilter characterEncodingFilter = new org.springframework.web.filter.CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return characterEncodingFilter;
}

Unable to configure json with spring - Request method 'GET' not supported

I'm not able to correctly configure json support with Spring 4.0.4. A json request results in:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.getHandlerInternal(246): - Looking up handler method for path /equipments/datatable.json
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.resolveException(134): - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver.resolveException(134): - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.resolveException(134): - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported
org.springframework.web.servlet.PageNotFound.handleHttpRequestMethodNotSupported(198): - Request method 'GET' not supported
I have an applicationContext.xml and a my-servlet.xml:
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/conf/applicationContext.xml
/WEB-INF/conf/my-security.xml
</param-value>
</context-param>
<servlet>
<servlet-name>losap</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/conf/my-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
applicationContext.xml
<mvc:annotation-driven />
<task:annotation-driven />
<tx:annotation-driven />
<context:component-scan base-package="com.htg.*">
<context:exclude-filter type="regex" expression="com\.htg\.myapp\.mvc"/>
</context:component-scan>
<bean id="messageAdapter"
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list>
<bean
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</util:list>
</property>
</bean>
my-servlet.xml
<mvc:annotation-driven/>
<context:component-scan base-package="com.htg.myspp.mvc" />
pom.xml
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
Controller
#Controller()
#RequestMapping(value = "/equipments")
public class EquipmentController extends BaseController {
#RequestMapping(value = "/datatable.json", method = RequestMethod.GET, headers = "Accept:*/*", produces = "application/json")
public #ResponseBody Equipment getEquipmentsDatatable(Model model) {
Equipment e = new Equipment();
e.setEquipmentName("Lathe 123");
e.setEquipmentNumber("12345TTY");
e.setId(89L);
return e;
}
}
jQuery
$.getJSON($('#ctxtrelurl').val() + 'equipments/datatable.json', function(e) {
console.log(e.equipmentName);
});
Chrome Dev. Tools output
I have a feeling it has something to do with having two separate context config. files. Any pointers will be greatly appreciated.
ok, my guess is, that spring doesn't map /datatable.json properly because of the "." I had similar problem at mapping this:
#RequestMapping(value="/somestuff/{fileName:.+}"
i had to put :.+ so spring can properly map the url.
spring seems to truncate ".something" in this case. I actually don't know if it's the case on regular mapping, without #PathVariable. But you could try to map your URL without the dot and check if it will help
And that's why spring try to call the {equipId} function, that is waiting for PUT request. That's why in the response header you see : allow:PUT

Spring Controller's URL request mapping not working as expected

I have created a mapping in web.xml something like this:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/about/*</url-pattern>
</servlet-mapping>
In my controller I have something like this:
import org.springframework.stereotype.Controller;
#Controller
public class MyController{
#RequestMapping(value="/about/us", method=RequestMethod.GET)
public ModelAndView myMethod1(ModelMap model){
//some code
return new ModelAndView("aboutus1.jsp",model);
}
#RequestMapping(value="/about", method=RequestMethod.GET)
public ModelAndView myMethod2(ModelMap model){
//some code
return new ModelAndView("aboutus2.jsp",model);
}
}
And my dispatcher-servlet.xml has view resolver like:
<mvc:annotation-driven/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp"/>
To my surprise: request .../about/us is not reaching to myMethod1 in the controller. The browser shows 404 error. I put a logger inside the method but it isn't printing anything, meaning, its not being executed.
.../about works fine! What can be the done to make .../about/us request work? Any suggestions?
You need to use #RequestMapping(value="/us", method=RequestMethod.GET) or you need to request about/about/us
Since you have mapped "/about" in your web.xml, the url it will pass will be like this www.xyz.com/about/*
As your configuration says it will work for
www.xyz.com/about/about/us
www.xyz.com/about/about
In order to to work properly either use
/* in web.xml instead of /about
or change the controller's endpoint to
#RequestMapping(value="/us", method=RequestMethod.GET)
#RequestMapping(value="/", method=RequestMethod.GET)
Okay I got the thing working, here are things I added in the dispatcher-servlet.xml:
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="alwaysUseFullPath" value="true" />
</bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="alwaysUseFullPath" value="true" />
</bean>

RequestMapping not working with multi-level URLs

I have a scenario where I'm making a simple get request through a link and my #RequestMapping configuration is not behaving as I'd expect.
Within an anchor tag I reference a url with the following pattern '/action-plan/export/pdf?token=xxx&taskId=1111&taskId=2222...'
Within my controller class I have this mapping at the class level:
#RequestMapping("/action-plan/export")
And this mapping at the method level
#RequestMapping(value="/pdf", method=RequestMethod.GET)
public String exportToPdf(#RequestParam("taskId") String[] taskIds,
#RequestParam("token") String[] encryptedEmplId, ModelMap model)
But every time I try this I get a 404 page not found error and the following Spring exception:
org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException: No matching handler method found for servlet request: path '/pdf', method 'GET', parameters map['taskId' -> array['1962326', '1962264', '1962317', '1962328', '1962324', '1962427', '1962325', '1962323', '1963147', '1962327', '1962318', '1962329', '1962330'], 'token' -> array['xxxx']]
I've noticed that when I remove the "/pdf?" portion of the link and remove 'value="/pdf"' from the method #RequestMapping it works fine. For the life of me I don't understand why adding /pdf to the url and RequestMapping is not working.
I think danny.lesnik's answer was pretty close but I'm writing my own answer so I can be more verbose.
I was working on a different project and figured out why the above doesn't work. In reference to my original question here is the relevant web.xml servlet mapping:
<servlet-mapping>
<servlet-name>spring-dispatcherServlet</servlet-name>
<url-pattern>/action-plan/export/*</url-pattern>
</servlet-mapping>
I noticed that whatever portion of the path I included in the of web.xml was not being included in the evaluation of RequestMapping values. I would have thought this bean configuration would have prevented that scenario (note the "alwaysUseFullPath" property):
<bean id="annotationHandlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="2"/>
<property name="alwaysUseFullPath" value="true"/>
</bean>
Maybe someone can shed some light on this detail for me.
In any case, thanks danny.lesnik
I recreated your problem and solved it by mapping servlet using .action extentions.
For example:
#Controller
#RequestMapping(value="/test")
public class DefaultController {
#RequestMapping(value="/pdf.action", method=RequestMethod.GET)
public ModelAndView indexView(#RequestParam("taskId") String[] taskIds,
#RequestParam("token") String[] encryptedEmplId){
ModelAndView mv = new ModelAndView("index");
return mv;
}
Spring XML mapping:
<context:annotation-config />
<context:component-scan base-package="com.vanilla.controllers" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
and this web.xml servlet mapping
<display-name>SpringMvcServlet</display-name>
<servlet>
<servlet-name>SpringMvcServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMvcServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
This code resolves this url
/test/pdf.action?token=3&token=4&taskId=4
flawless.

Resources