Spring MVC allows you to serialize objects with @ResponseBody to any format – it has built-in converters for JSON and XML. However, even though your application may support both, you may need a default in case the Accept header is not set. Furthermore (this is a strange case, but we had it), you may want different defaults for different URLs.
As far as I know you can’t choose which of the converters to be used – they are ordered and the first converter in the list gets picked up and serializes the response.
My solution to the problem is trivial, but not the first thing you’d think about. Use a Filter, and in case the client hasn’t supplied an Accept header, wrap the request and make it return the default Accept header, as if the client has set it. That way, whenever spring-mvc invokes the getHeader() method, it will get the desired Accept header.
/** * Filter that is needed to set the default Accept header per gateway. * According to previous API specifications, each gateway had a default serialization format. Unfortunately these formats differ, * and spring can't have a default-per-url. That's why this filter wraps the request in case there is no Accept header and returns * the default one depending on the url * * @author bozho * */ public class DefaultAcceptHeaderSettingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; String acceptHeader = httpRequest.getHeader("Accept"); if (StringUtils.isBlank(acceptHeader)) { chain.doFilter(new DefaultAcceptHeaderHttpServletRequestWrapper(httpRequest), response); } else { chain.doFilter(httpRequest, response); } } @Override public void destroy() { } public static class DefaultAcceptHeaderHttpServletRequestWrapper extends HttpServletRequestWrapper { public DefaultAcceptHeaderHttpServletRequestWrapper( HttpServletRequest request) { super(request); } @Override public String getHeader(String name) { if (name.equals("Accept")) { if (getRequestURI().contains("/service1")) { return "application/json"; } else if (getRequestURI().contains("/service2")) { return "application/xml"; } } return super.getHeader(name); } } }
(btw, please let me know if there’s a native spring way to do that)
Spring MVC allows you to serialize objects with @ResponseBody to any format – it has built-in converters for JSON and XML. However, even though your application may support both, you may need a default in case the Accept header is not set. Furthermore (this is a strange case, but we had it), you may want different defaults for different URLs.
As far as I know you can’t choose which of the converters to be used – they are ordered and the first converter in the list gets picked up and serializes the response.
My solution to the problem is trivial, but not the first thing you’d think about. Use a Filter, and in case the client hasn’t supplied an Accept header, wrap the request and make it return the default Accept header, as if the client has set it. That way, whenever spring-mvc invokes the getHeader() method, it will get the desired Accept header.
/** * Filter that is needed to set the default Accept header per gateway. * According to previous API specifications, each gateway had a default serialization format. Unfortunately these formats differ, * and spring can't have a default-per-url. That's why this filter wraps the request in case there is no Accept header and returns * the default one depending on the url * * @author bozho * */ public class DefaultAcceptHeaderSettingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; String acceptHeader = httpRequest.getHeader("Accept"); if (StringUtils.isBlank(acceptHeader)) { chain.doFilter(new DefaultAcceptHeaderHttpServletRequestWrapper(httpRequest), response); } else { chain.doFilter(httpRequest, response); } } @Override public void destroy() { } public static class DefaultAcceptHeaderHttpServletRequestWrapper extends HttpServletRequestWrapper { public DefaultAcceptHeaderHttpServletRequestWrapper( HttpServletRequest request) { super(request); } @Override public String getHeader(String name) { if (name.equals("Accept")) { if (getRequestURI().contains("/service1")) { return "application/json"; } else if (getRequestURI().contains("/service2")) { return "application/xml"; } } return super.getHeader(name); } } }
(btw, please let me know if there’s a native spring way to do that)
Recent Comments