sravan ganji
sravan ganji

Reputation: 5125

how to return the xml or json respoonse based on url extension

I have a java service which is built on jaxrs and it is returning the response based on url extension. For example: http://localhost:8080/employees returns xml by default, http://localhost:8080/employees.json returns json data.

So there are plenty of services and UI consuming this Jaxrs service, now I am converting this service from jaxrs, springbased restservice, how can I replicate the same thing with springbased restcontroller?

If I pass the accept: application/json or application/xml, it is working fine but I am looking for a solution for URL extension.

I have tried 1) WebMvcConfigurer 2) interceptors/filters but nothing is working

1) WebMvcConfigurer

package com.example.spring_rest_to_graphql;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(true)
                  .favorParameter(false)
                  .ignoreAcceptHeader(true)
                  .useRegisteredExtensionsOnly(true)
                  .defaultContentType(MediaType.APPLICATION_JSON)
                  .mediaType("json", MediaType.APPLICATION_JSON)
                  .mediaType("xml", MediaType.APPLICATION_XML);
    }
}

2) interceptors/filters

package com.example.spring_rest_to_graphql;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class ContentNegotiationInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        if (requestURI.endsWith(".json")) {
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        } else if (requestURI.endsWith(".xml")) {
            response.setContentType(MediaType.APPLICATION_XML_VALUE);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // No implementation needed
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // No implementation needed
    }
}

So after all these changes when I hit this endpoint http://localhost:8080/employees, am getting an xml response, but when I hit this endpoint http://localhost:8080/employees.json I am getting 404 error page.

Upvotes: 0

Views: 49

Answers (2)

sravan ganji
sravan ganji

Reputation: 5125

filters and interceptors did not help.

found an alternative work around.

@GetMapping(value = "/employees", produces = { MediaType.APPLICATION_XML_VALUE })
List<Employee> all() {
    return repository.findAll();
}


@GetMapping(value = "/employees.json", produces = { MediaType.APPLICATION_JSON_VALUE })
List<Employee> allWithExtension() {
    return repository.findAll();
}

Upvotes: 1

Tokazio
Tokazio

Reputation: 530

For the 404 it's the endpoint configuration that is wrong

/employees is not /employees.json

You need a way to handle the '.json'

Maybe a GetMapping("/employees{ext}" ?

You changed the contentType of the response in the preHandle (before handler execution)

    String requestURI = request.getRequestURI();
        if (requestURI.endsWith(".json")) {
            **response.setContentType**(MediaType.APPLICATION_JSON_VALUE);
        } else if (requestURI.endsWith(".xml")) {
            **response.setContentType**(MediaType.APPLICATION_XML_VALUE);
        }
        return true;
    }

but it's the content type of the request that should be changed no ?

    String requestURI = request.getRequestURI();
        if (requestURI.endsWith(".json")) {
            **request.setContentType**(MediaType.APPLICATION_JSON_VALUE);
        } else if (requestURI.endsWith(".xml")) {
            **request.setContentType**(MediaType.APPLICATION_XML_VALUE);
        }
        return true;
    }

And beware of requestURI.endsWith(".json") if you add some request parameters. Maybe it's better to use requestURI.getQueryString.endsWith(".json")

This one can help you too Spring does not ignore file extension

Upvotes: 0

Related Questions