Well I have a strange problem with executing a "DELETE" HTTP request in Spring.
I have a controller method which I have mapped a DELETE request to:
#RequestMapping(value = "/{authorizationUrl}",method=DELETE)
public void deleteAuthorizationServer(
#RequestHeader(value="Authorization") String authorization,
#PathVariable("authorizationUrl") String authorizationUrl)
throws IOException {
System.out.println("TEST");
}
The controller is mapped using #RequestMapping("/authorization_servers");
When I send a request through my DEV Http Client, I am getting the response : 405 Http method DELETE is not supported by this URL.
The request looks like this:
DELETE localhost:8080/authorization_servers/asxas
Headers:
Authorization: "test:<stuff>"
If someone can look into this and help me, I would be grateful
This will work:
#RequestMapping(value = "/{authorizationUrl}", method = DELETE)
#ResponseBody
public void deleteAuthorizationServer(
#RequestHeader(value="Authorization") String authorization,
#PathVariable("authorizationUrl") String authorizationUrl
){
System.out.printf("Testing: You tried to delete %s using %s\n", authorizationUrl, authorization);
}
You were missing #ResponseBody. Your method was actually getting called; it was what happened after that that was producing the error code.
Your annotation should look like this:
#RequestMapping(value = "/{authorizationUrl}",method=RequestMethod.DELETE)
I don't know where you got that DELETE variable from. :-)
If the #RequestMapping pattern doesn't match or is invalid, it results in a 404 not found. However, if it happens to match another mapping with a different method (ex. GET), it results in this 405 Http method DELETE is not supported.
My issue was just like this one, except my requestMapping was the cause. It was this:
#RequestMapping(value = { "/thing/{id:\\d+" }, method = { RequestMethod.DELETE })
Do you see it? The inner closing brace is missing, it should be: { "/thing/{id:\\d+}" } The \\d+ is a regular expression to match 1 or more numeric digits. The braces delimit the parameter in the path for use with #PathVariable.
Since it's invalid it can't match my DELETE request:
http://example.com/thing/33
which would have resulted in a 404 not found error, however, I had another mapping for GET:
#RequestMapping(value = { "/thing/{id:\\d+}" }, method = { RequestMethod.GET })
Since the brace pattern is correct, but it's not a method DELETE, then it gave a error 405 method not supported.
I needed to return ResponseEntity<Void> (with custom response status) instead of setting custom response status on HttpServletResponse (from endpoint method param).
ex: http://shengwangi.blogspot.com/2016/02/response-for-get-post-put-delete-in-rest.html
also make sure you're calling it with "Content-Type" header="text/html". If not, then change it or specify it in the requestMapping. If it doesn't match, you get the same 405.
Related
I want to make a GET request to my server that receives two parameters, uniqueConfig and commitHash. The code for this operation in my Controller class is as follows:
#GetMapping("/statsUnique")
public ResponseEntity<Object> hasEntry(#RequestParam("uniqueConfig") String uniqueConfig,
#RequestParam("commitHash") String commitHash) {
Optional<Stats> statsOptional =
codecService.findByUniqueConfigAndCommitHash(uniqueConfig, commitHash);
if (statsOptional.isPresent()) {
return ResponseEntity.status(HttpStatus.OK).body(true);
}
return ResponseEntity.status(HttpStatus.OK).body(false);
}
The issue is, when I try to make the GET request using Postman, the server returns a 400 - Bad Request with the following error message:
MissingServletRequestParameterException: Required request parameter 'uniqueConfig' for method parameter type String is not present]
my JSON on Postman looks like this:
{
"commitHash": "ec44ee022959410f9596175b9424d9fe1ece9bc8",
"uniqueConfig": "bowing_22qp_30fr_29.97fps_fast-preset"
}
Please note that those aren't the only attributes and I've tried making the same request with all of them on the JSON. Nonetheless, I receive the same error.
What am I doing wrong here?
A GET request doesn't (or at least shouldn't) have a body. Parameters defined by the #RequestParam annotations should be sent in the query string, not a JSON body, i.e., the request should be something like
http://myhost/statsUnique?commitHash=commitHash&uniqueConfig=bowing_22qp_30fr_29.97fps_fast-preset
I am working on (Maven Project) REST with Java (JAX-RS) using Jersey. I am trying to delete a Module according to the passed id
#DELETE
#Path("delete/{id}")
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public Module deleteModuleById(#PathParam("id") Long id) {
return repository.delete(id);
}
I am getting 405 - Method not allowed from tomcat server, not sure what am I doing wrong.
This is the Delete Method:
public Module delete(long id) {
EntityManager em = EM_FACTORY.createEntityManager();
em.getTransaction().begin();
Module m = em.find(Module.class, id);
if (m != null) {
em.remove(m);
} else {
throw new IllegalArgumentException("Provided id " + id + " does not exist!");
}
em.getTransaction().commit();
em.close();
return m;
}
Postman request for all Module:
Postman request for delete module with id=1:
Project Structure:
Your code seems to be ok. Check your Sending method. Please take into account that IllegalArgumentException will probably lead to 500 - Server error
Check via Curl
curl -X DELETE <YOUR HOST>/delete/123
Or check via any external resources like https://reqbin.com/, postman, etc.
As your code seems fine and you haven't added your postman request, I assume you may have set the wrong method type in your request. you set your request like this image below:
Please, replace base_url and your_id with your actual values
N.B: check the DELETE method I have set on left of the URL
#Consumes({MediaType.APPLICATION_JSON})
Postman automatically attaches the Content-Type header according to the settings of your request's body.
Your requests are set to HTML, not JSON.
It should give a different error, but this should cause an issue here.
405 Method not allowed occurs when you try to POST while the method is GET, for example.
In the postman requests I don't see you putting the param id. So, the call you are making will look like /api/modules/delete while it should have been /api/modules/delete/1. And if there is a method like api/modules/{x}, it will call this method finally creating the 405.
I have an web application and I'm trying to creat a simple POSt method that will have a value inside the body request:
#RequestMapping(value = "/cachettl", method = RequestMethod.POST)
#CrossOrigin(origins = "http://localhost:3000")
public #ResponseBody String updateTtl(#RequestBody long ttl) {
/////Code
}
My request which I call from some rest client is:
POST
http://localhost:8080/cachettl
Body:
{
"ttl": 5
}
In the response I get 403 error "THE TYPE OF THE RESPONSE BODY IS UNKNOWN
The server did not provide the mandatory "Content-type" header."
Why is that happening? I mention that other GET requests are working perfectly.
Thanks!
Edit:
When I tried it with postman the error message I got is "Invalid CORS request".
Spring application just doesn't know how to parse your message's body.
You should provide "header" for your POST request to tell Spring how to parse it.
"Content-type: application/json" in your case.
You can read more about http methods here: https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data
Updated:
Just in case of debug, remove useless annotations to test only POST mechanism. Also, change types of arg and return type. And try to use case-sensitive header.
#RequestMapping(value = "/cachettl", method = RequestMethod.POST)
public void updateTtl(#RequestBody String ttl) {
System.out.println("i'm working");
}
Since the error is about the response type, you should consider adding a produces attribute, i.e :
#RequestMapping(value = "/cachettl", method = RequestMethod.POST, produces=MediaType.APPLICATION_JSON_VALUE)
Since you are also consuming JSON, adding a consumes attribute won't hurt either :
#RequestMapping(value = "/cachettl", method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE, produces=MediaType.APPLICATION_JSON_VALUE)
The error message is slightly misleading. Your server code is not being hit due an authentication error.
Since you say spring-security is not in play then I suspect you're being bounced by a CORS violation maybe due to a request method restriction. The response body generated by this failure (if any at all) is automatic and will not be of the application/json type hence the client failure. I suspect if you hit the endpoint with something that doesn't care for CORS such as curl then it will work.
Does your browser REST client allow you to introspect the CORS preflight requests to see what it's asking for?
I have a servlet where in general I return text/csv as response. So a plain comma separated string.
BUT: in case of exceptions, I'd want to show just some error text as response. But instead Spring generates a custom ResponseEntity object, then tries to convert this response to csv which obviously fails.
Is it possible to replace the requested format to format=json, and then just return the default Spring error response?
#RestController
public class CsvServlet {
#RequestMapping(value = "/test", produces = "text/csv")
#ResponseBody
public String errorCsv(HttpServletRequest request) {
return "some, plain, text";
}
}
Usage: localhost:8080/test?format=csv
When having spring.security.enabled=true, this will first validate the basic auth credentials. If they fail, spring will automatically redirect to /error servlet.
Thereby BasicErrorController.error() method comes in, catching the error and generating a ResponseEntity with error attributes like timestamp, exception, path, etc.
Problem: now an Object of type ResponseEntity is returned. This is fine as long as the format parameter is either ?format=json/xml. As the response can then be properly converted.
But in my special case, where I request ?format=csv, the conversation will fail, leading to:
Response could not be created:
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not
find acceptable representation
This is partially true, moreover misleading because the user should directly see that the authentication credentials have been invalid. Because in general I'm accepting csv, but Spring and the mappers don't know how to convert a ResponseEntity to a plain format like csv.
Question: how can I preserve the original exception? So that I could just return a plain text error message. It would also be fine if I could return a application/json response in this case!
Workaround as follows for the moment: override the /error servlet handler, and if the ?format parameter is not either json/xml, just return the original http status error without a body.
Thus spring cannot fail on converting the body into plain format and return the response correctly (but without exception details in the body).
#Controller
public class WorkaroundBasicErrorController extends BasicErrorController {
//default constructor from ErrorMvcAutoConfiguration
public DefaultBasicErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties,
ObjectProvider<List<ErrorViewResolver>> errorViewResolversProvider) {
super(errorAttributes, serverProperties.getError(), errorViewResolversProvider.getIfAvailable());
}
#RequestMapping
#ResponseBody
#Override
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
String format = request.getParameter("format");
return (StringUtils.containsAny(format, "json", "xml"))
? super.error(request)
: new ResponseEntity<>(getStatus(request)); //neglect body for plain formats
}
}
Try to use a void #ExceptionHandler, and write error message directly in HttpResponse
In spring MVC...
I have to reload a page after the record is updated. So in the action method I am returning String and in return I am returning
return "redirect:/recordList";
When but it is giving the exception on the page
HTTP Status 405 - Request method 'GET' not supported
There is no exception coming on the logs.
My controller method looks like
#RequestMapping(value= "/recordList", method = RequestMethod.POST)
public ModelAndView getAssetListForUser(#RequestParam("ldapId") String ldapId,
final HttpServletRequest request){
Also, because I need the value if ldapId in the controller method, I am binding it in the calling method like this
request.setAttribute("ldapId", assetAssetEmp.getAssetEmpId());
Please help.
It looks like your /recordList controller method only supports RequestMethod.POST.
hence you're getting the 405 GET Method not allowed error, since the redirect will issue a GET request.
to solve for it, try to give a GET version of your controller action. (the assetlist method) so that once the update happens, the asset list of the user can be returned via the GET method.
The #RequestMapping annotation is your way to specify when your method is going to be called in an annotated controller. The RequestMethod.GET and RequestMethod.POST arguments allow you to respond to the specific HTTP request type.
providing method = RequestMethod.POST to controller method actually making method to accept only HTTP POST requests.
RequestMethod