this may or may not be a somewhat long post, but I'm going to be pasting every single piece of information relating to this issue and the method I am testing, from Controller class with method to the a.jax snippet. I have asked about 4-6 developers and no one can find out the reason why its giving me a 415 error instead of a 200, because it just seems like I am doing everything correct. I just need some fresh eyes and new perspectives, hopefully someone could help me solve this. I will be pasting the classes and the relevant pieces now, and then a couple comments after the snippets.
Controller class
#Controller
#RequestMapping(value = "/user")
public class Controller
{
#Autowired
private Service service;
public Controller() {
}
#RequestMapping(value = "/landing/{age}/{name}/{title}/{family}/{gender}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
public #ResponseBody String update(#RequestBody HouseModel model, #PathVariable int age, #PathVariable String name, #PathVariable String title, #PathVariable String family, #PathVariable String gender)
{
String result = service.update(model, age, name, title, family, gender);
// this will just return the string "Success" if update works or "Failed" if query is
wrong or not found
return result;
}
Service Class
#Service
public class Service
{
#Autowired
Dao dao;
public Service() {
}
public String update(HouseModel model, int age, String name, String title, String family)
{
return dao.update(HouseModel model, int age, String name, String title, String family);
}
}
Dao class
#Repository
public class Dao
{
public Dao () {
}
public String update(HouseModel model, int age, String name, String title, String family)
{
String result = "";
//some long query that updates the table and will populate result as "Success" or "Failed"
return result
}
}
Controller test class
#EnableWebMvc
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:applicationContext-testing.xml",
"classpath:applicationContext-EIPW.xml"})
public class ControllerTest {
#Autowired
private Controller controller;
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#Before
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void test_update() throws Exception {
String URI = "/user/landing/22/Test/Mr/Yes/Male";
String content = "{\n \"HouseId\": 5,\n \"DateOfPurchase\": \"2019-01-01\",\n \"Price\": 100,\n \"Floors\": 5,\n \"Style\": \"Victorian\",\n}";
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.put(URI).contentType(MediaType.APPLICATION_JSON).content(content).accept(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mockMvc.perform(requestBuilder).andDo(MockMvcResultHandlers.print()).andReturn();
}
j.ajax
$j.ajax({
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
type: "PUT",
async: false,
data: JSON.stringify(
buildEdit(editRecords[i], ecRecord)
),
url:
"/user/landing/22/Test/Mr/Yes/Male",
dataType: "text"
printed error message
MockHttpServletRequest:
HTTP Method = PUT
Request URI = /user/landing/22/Test/Mr/Yes/Male
Parameters = {}
Headers = {Content-Type=[application/json], Accept=[application/json]}
Handler:
Type = controller.Controller
Async:
Was async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
MockHttpServletResponse:
Status = 415
Error message = null
Headers = {Accept=[application/octet-stream, */*, text/plain;charset=ISO-8859-1, */*, application/xml, text/xml, application/*+xml, application/x-www-form-urlencoded, multipart/form-data]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Some Comments:
So I've had over 50 stack overflow tabs open relating to the same problem, and a lot of them had similar solutions that seemed so simple. Here are some, if not all of the things I did in attempts to try and solve this problem:
Switched around the content-type and accepts headers of requestBuilder to be MediaTypes of APPLICATION_JSON or APPLICATION_JSON_VALUE or ALL_VALUE, etc
Added produces or consumes = "application/json" or MediaType.APPLICATION_JSON/APPLICATION_JSON_VALUE/ALL_VALUE into the requestMapping().
Played around with a.jax to change content-type or accepts around
A couple of other things that I don't remember, but alas the 415 status is still here
I also do have setters and a default constructor in the HouseModel, and default constructors in every layer. I am 99.9% sure I have tried almost everything, if not everything, unless I am just missing something and am being stupid then yeah. I sent the request with the body as JSON raw an as:
{
"HouseId": 5,
"DateOfPurchase": "2019-01-01",
"Price": 100,
"Floors": 5,
"Style": "Victorian",
}
and it returned back success, I will attach its headers here:
[![Picture Link][1]][1]
[1]: https://i.stack.imgur.com/AqKnY.png
There is something interesting though, I did get one method to work but it required no arguments in its parameters, it was just a get method (dao calls database to store stuff in a list):
**Controller method**
#RequestMapping(value = "/levels", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody String getLevels() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
// there is a long logic after this map to populate the map
Map<LevelObject, List<LevelObject>> map = new HashMap<LevelObject, List<LevelObject>>();
return mapper.writeValueAsString(map);
}
This is such a simple test and it worked perfectly fine, giving me a status 200 and my expected result.
**Test class method**
#Test
public void test_getLevels() throws Exception {
String URI = "/user/levels";
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(URI).accept(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mockMvc.perform(requestBuilder).andExpect(status().isOk()).andReturn();
}
**j.ajax for the getLevels method**
$j.ajax({
type: "POST",
url: "user/levels",
async: false,
dataType: "json",
Thank you so much!
Though I am not a front-end developer, I am sure that problem is in below line
data: JSON.stringify(
buildEdit(editRecords[i], ecRecord)
)
Reason - I tested your code locally. Code works fine from postman, if I select request body as raw and type as JSON
But if select request body as raw and type as "TXT". I am getting same error as you.
[![enter image description here][2]][2]
So, I am sure that your request body is not being built as JSON. rather it is being sent as some other format. Hence, the error.
[2]: https://i.stack.imgur.com/cqSCC.png
Also, you can try to change dataType: "text" to dataType: "json"
Please try the below,
$j.ajax({
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
type: "PUT",
async: false,
data:
buildEdit(editRecords[i], ecRecord),
url:
"/user/landing/22/Test/Mr/Yes/Male",
dataType: "json"
Remove converting the json to String
Change the dataType to json
I am passing JSON data from jQuery to my Java controller and I am using #RequestBody, but I am getting an exception saying:
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
The data which I am passing is:
myData = {
"source": "CSS",
"type": "CSS2",
"typeValue": "value",
"textarea_value": " desc"
}:
The AJAX call I am using to pass this data is:
$.ajax({
url: './common/deleteData',
type: 'POST',
data: myData,
success: function(data) {
alert("Successfully Deleted Source..");
},
error: function(data) {}
});
My Java Controller is as below
#RequestMapping(value = "/common/deleteData", method = RequestMethod.POST, consumes = {"application/x-www-form-urlencoded; charset=UTF-8"})
public String deleteData(#RequestBody SourceDelete sourcedelete, final HttpServletRequest request, final RedirectAttributes rdtAttribs) throws ApplicationException
{
LOGGER.entry("Deleting the Merge Preference Details");
System.out.println(sourcedelete.getSource());
return null;
}
My POJO object is as below:
public class SourceDelete {
private String source;
private String type;
private String typeValue;
private String textarea_value;
//Setters and Getters
}
Can someone please help me figure out why I am getting this error and how I should fix it.
remove the #RequestBody annotation,
#RequestMapping(value = "/common/deleteData", method = RequestMethod.POST, consumes = {"application/x-www-form-urlencoded; charset=UTF-8"})
public String deleteData(SourceDelete sourcedelete, final HttpServletRequest request, final RedirectAttributes rdtAttribs) throws ApplicationException
{
LOGGER.entry("Deleting the Merge Preference Details");
System.out.println(sourcedelete.getSource());
return null;
}
I'm sending an application/json type from the postman client to a java API that forwards all the requests to the specific API for that case.
On this concrete case, I have a login API and I want to center code heard this JSON:
JSON from the postman
{
"name": "random name",
"password": "random passwd"
}
The API that does the forward
#RequestMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public String redirectHttpRequest(HttpServletRequest request, #Value("${endpoint}") String newURL,
HttpServletResponse response) throws IOException {
try {
RestTemplate restTemplate = new RestTemplate();
String result = null;
String body = IOUtils.toString(request.getReader());
if (request.getMethod().equals("GET")) {
// result = restTemplate.getForObject(redirectUrl.toString(), String.class);
} else if (request.getMethod().equals("POST")) {
result = restTemplate.postForObject(newURL, body, String.class);
}
return result;
} catch (HttpClientErrorException e) {
System.out.println(e);
return "OLA";
}
}
That new URL is the URL were the other API is (which, in this case, is localhost:8080 and is from the application.properties file).
I've tested the login API through postman and it works, but when I try to connect it to that forward API I got the following error:
org.springframework.web.client.HttpClientErrorException: 415 null.
I would like to know what I am doing wrong or an alternative way to do it.
Postman call
Second endpoint code
The value of the body passed to the second endpoint
The User class
public class User {
private String name;
private String password;
private List<String> groups;
public User(String name, String password) {
this.name = name;
this.password = password;
this.groups = new ArrayList<String>();
}
public User() {
}
public String getName() {
return this.name;
}
public String getPassword() {
return this.password;
}
public List<String> getGroups() {
return this.groups;
}
public String toString() {
return "User: " + this.name + "\nGroups: " + this.groups;
}
The problem is that you are getting the 415 error code. That means that your /login endpoint is not expecting the payload type you are sending him, see here
415 (Unsupported Media Type)
The 415 error response indicates that the API is not able to process the client’s supplied media type, as indicated by the Content-Type request header. For example, a client request including data formatted as application/xml will receive a 415 response if the API is only willing to process data formatted as application/json.
For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format.
I think is this because when you call postForObject, you are not telling the media type of your payload. So instead of sending the json String alone, you need to wrap it into an HttpEntity that holds the body and also a header that specifies the media type of the payload you are forwarding. Try this out:
...
} else if (request.getMethod().equals("POST")) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
HttpEntity<String> entity = new HttpEntity<>(body, headers);
result = restTemplate.postForObject(newURL, entity, String.class);
}
...
I am making a simple API using Spring. and i am getting this error while uploading and mapping file.
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
this is my Controller ->
#RequestMapping(value = "/Hi", method = RequestMethod.POST, produces = { "application/json" })
#ResponseBody
public BasicResponse UploadData(#RequestBody CropImageData cropImageData, HttpServletRequest request) {
BasicResponse basicResponse = new BasicResponse();
System.out.println(cropImageData.getCropId());
return basicResponse;
}
My cropImageData model class ->
public class CropImageData {
#JsonProperty("cropImages")
private MultipartFile[] cropImages;
#JsonProperty("cropId")
private String cropId;
public MultipartFile[] getCropImages() {
return cropImages;
}
public void setCropImages(MultipartFile[] cropImages) {
this.cropImages = cropImages;
}
public String getCropId() {
return cropId;
}
public void setCropId(String cropId) {
this.cropId = cropId;
}
}
this is how i am sending request via POSTMAN.
With Postman, you are sending a HTTP post form-data but your end point is not configured to receive this format (the consumes = { "multipart/form-data" } annotation is missing).
Instead of your model class, you should change the signature of your method to something like that:
public BasicResponse UploadData(#RequestPart("cropId") String cropId, #RequestPart("cropImages") MultipartFile file)
Spring throws an error when I send json array. I am not sure what I am missing here.
RequestBody
{
"deliverySessionId":"c1fb327b-98a8-46d4-9e82-ce7507b5be93",
imageNames: ["name1", "name2"]
}
Endpoint
#RequestMapping(value = { "/examImages/" }, method = { RequestMethod.POST } )
public #ResponseBody ImageResponseCommand streamExamImages( #RequestBody ImageResponseCommand imageResponseCommand ) {
Error
The request sent by the client was syntactically incorrect.
It works fine if my request doesn't contain imageNames property.
{ "deliverySessionId":"c1fb327b-98a8-46d4-9e82-ce7507b5be93" }
Your JSON string isn't formatted properly. Object key's need to be wrapped in quotes.
{
"deliverySessionId":"c1fb327b-98a8-46d4-9e82-ce7507b5be93",
"imageNames": ["name1", "name2"]
}