Multiple Content-type in Spring MVC - spring

Can we have multiple content-type in Spring MVC request header?
I'm passing:
{Content-type = application/json, text/plain}
through Postman to my API. Currently, I'm getting org.springframework.web.HttpMediaTypeNotSupportedException: Invalid mime type ....
I wanted to know, is there something with my input values, or we can't have multiple content-type in our header.
Controller:
#RequestMapping(value = "/addressees", produces = APPLICATION_JSON_UTF8_VALUE, method = GET)

Yes, spring mvc request mapping supports multiple consumes MIME type , sample looks like
#RequestMapping(value = "/something", method = PUT,
consumes = {APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE},
produces = {APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE})
public SomeObject updateSomeObject(SomeObject acct) {
return doStuff(acct);
}
Add consumes part in requestmapping like - consumes = {APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE}
For know more, refer this link -
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html

Your request header can have one content-type per request. You specify to the server what type of data are actually being sent.
Your server/API endpoint can support multiple.
So if your request specifies both application/json and text/plain at the same time, I believe it is a problem with your request.

Yes, RequestMapping.consumes accepts an array of Mime types
String[] consumes() default {};
Note that you have to use consumes to define the incoming MIME types. produces is for the outgoing type.

Related

Feign get request with body

For some reason I need to call a GET method API and pass json request body for it. I really couldn't find an example for it. I wonder if it is even supported using feign.
How can I do that using feign?
Yes, Feign supports it. You can do the same as with POST requests:
#FeignClient(name = "clientName", url = "http://localhost:8888")
public interface SampleFeignClient {
#GetMapping("/remote")
String test(#RequestBody SampleRequestBody sampleRequestBody);
}
But be aware: a lot of servers ignore body or even refuse that kind of "non-standard" requests completely (GET or HEAD with request bodies).
According to the documentation the correct way to do it would be to use the #SpringQueryMap annotation.
#FeignClient(name = "clientName", url = "http://localhost:8888")
public interface SampleFeignClient {
#GetMapping("/remote")
String test(#SpringQueryMap SampleRequestBody sampleRequestBody);
}
You can find more information here

Spring receiving empty body

I'm using Spring for my backend. I have the following code:
#RequestMapping(value = "/test", method = RequestMethod.POST)
#CrossOrigin
public void test(HttpServletRequest request) {
System.out.println(request.getParameterMap().size());
System.out.println(new JSONObject(request.getParameterMap()));
}
When I send JSON data using Postman, I get a map of all the parameters I've sent.
But when I'm making the same call from my website, I get an empty map with size 0. I do not get any error or exception on both front and back sides.
What could be the reason?
Thank you
Most probably getParameterMap() is really empty in your case, because parameters are not passed as query, but as a body (content) of HTTP request when it is sent from your web-site.
It can also be affected by the Content-Type and Accept headers of the HTTP request.
According to official documentation ServletRequest.getParameterMap() returns:
For HTTP servlets, parameters are contained in the query string or posted form data.
Usually "posted form data" implies: HTTP header Content-Type: application/x-www-form-urlencoded and URL encoded name-value pairs of parameters in the content of HTTP request.
If your web-site sends application/json, any other content type, or does not define content type at all, it might not be properly mapped into the request parameters by servlet container. In this case you should look into the body of HTTP request (ServletRequest.getReader()) to get the payload, or let Spring MVC do that (e.g. #RequestBody annotation).

Spring Rest Service Return Type

I have a rest service in spring which can return a string or a json. For this in my js code while sending the ajax request, i have specified datatype as "*". I wanted to know how can i handle this in spring service
All produces type are available in org.springframework.http.MediaType and for your requirement you can pass */*.
Constant for that is MediaType.ALL_VALUE in java code.
But if you know that your service always return JSON then I prefer to use MediaType.APPLICATION_JSON_UTF8_VALUE instead of MediaType.ALL_VALUE.
you can add attribute " produces" on your RequestMapping annotation:
#RequestMapping(value = "/yourPath", method = GET,
produces = { "application/json", "application/xml",....all what you want as type})

Spring #JsonView how can use request parameter or header

#JsonView
how can use like parameter from request:
#JsonView(header="range")
when response value,read request header range to exclude/include some field
JsonView provides "static" view mapping. so for your dynamic behaviour you can do like this:
// actual request handling is happened here
private ResponseEntity<SomeObject> processRequest();
// request handling with view limit in result
#JsonView(YourDefinedView.class)
#RequestMapping(value = "/request", headers={"range=include"})
public ResponseEntity<SomeObject> processWithView() {
return processRequest();
}
// request handling without view (no headers specified)
#RequestMapping(value = "/request")
public ResponseEntity<SomeObject> processWithoutView() {
return processRequest();
}
this will map your client to same request url, but depending on header it will provide view or not. Than you can create a set of methods, that will be using different #JsonView depending on headers information.
But with this you will limit only the data transfered to client, and the whole data load will happen on server. For example with database and JPA, if you would like not to fetch from database all that data you will end with javax.persistence.NamedEntityGraphs, which will change the general logic of your application - and will at the end of the day produce 2 different methods.
And if you would like to expose custom header with list of fields, to be serialized - custom DTO object, or Map<String, Object> (ugly-ugly-ugly) or custom HandlerMethodReturnValueHandler comes to your help.

Webapi model binder not constructing a complex type?

I have this api action :
[Route("~/api/products/{productCode}/price")]
public IHttpActionResult PutProductPrice(string productCode,
PriceBindingModel binding) {
when I send a request to this endpoint with no request body like this :
Accept: application/json
Content-Type: application/json
Content-Length: 0
In the body of the PutProductPrice binding is null. (different from MVC)
I'm used to Model Binder create a PriceBindingModel using it's default parameterless constructor and assigning the values (in this case there is none)
Is this supposed behavoir ? should I check if Model is null in all my api requests ?
I guess this is a bug or some other problem I'm not seeing.
Note: Sending {} (empty object) on the request, makes the BindingModel be created and getting the expected bad request with a failed modelstate. (which I supposed should happen in the first scenario (sending an empty body) as well.
Note 2: doing this in the first line on the controller make it work as expected:
binding = binding ?? new PriceBindingModel();
ideas ?

Resources