-Code for Exposing Resource:
#Path("/messages")
public class MessageResource {
#PUT
#Path("/{messageId}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_HTML})
public MessageEntity updateMessage(MessageEntity messageEntity, #PathParam("messageId") long messageId) {
messageEntity.setMessageId(messageId);
return new MessageService().updateMessage(messageEntity);
}
}
URI to test: http://localhost:8080/rest-webservice-app/webapi/messages/1
I am testing using Postman (So not a problem with Method being called), and every time I do get the same error :
HTTP Status 405 – Method Not Allowed
I snooped around stack overflow and other blogs/forums for the answer, but nothing seems to work.
Read about the firewalls of the PUT/DELETE request too but doesn't seem to be a firewall issue in case we are testing in local dev env.
The POST and GET are working fine.
The issue is with DELETE and POST.
Can somebody help me out with this?
Thanks.
Related
I am trying to send a Delete request but it doesn't work. Oddly enough it works if I just change #DELETE to #GET.
#Stateless
#Path("orders")
public class OrderRestful {
#Inject
BestellungRepository bestellrepo;
#DELETE
#Path("{id}")
public Response deleteBestellung(#PathParam("id") long id){
Bestellung b = bestellrepo.getBestellungById(id);
if(b == null){
return Response.status(Status.NOT_FOUND).build();
}
bestellrepo.deleteBestellung(b);
return Response.noContent().build();
}
}
Since it works fine with #GET so I know the code per se is not the problem. I guess there is a syntax problem somewhere I am missing but I don't know where. I am using glassfish 5 and it is a jersey project.
Edit: I tried to make it a void method. Didn't work. I tried not using Path. It didn't work.
It turns out that the code itself wasn't wrong at all. The tool I tested it with was. I tested it with Advanced Rest Client for Chrome and it throws Bad Request. When I test it with the RestClient for Firefox it works without a problem. So the Problem is solved now :)
I am using Jersey Rest implementation. There are one Rest Services Called HelloWorld. See the below code.
Please consider this code as reference not as compiled code.
#Path("helloWorld")
public class HelloWorld{
#Path("test")
#Produces(...)
#Consum(...)
#GET
public Response test(Person person){
System.out.println(person);
}
}
I am using Jersey client to sent the request.
Here My question is apart from POST method is there any way to send the object to GET method directly. Instead of QueryString.
Please let me if there is any way to do so.
Thanks
So the problem shouldn't be with the server. I did a few tests on different servers (not weblogic as I don't use it) and all of them seem to have no problems accepting a body in the GET request. The problem seem to be with the client. To test I used the following code
ClientBuilder.newClient()
.target("http://localhost:8080/api/get-body")
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
.request()
.method(HttpMethod.GET, Entity.text("Hello World"));
The SUPPRESS_HTTP_COMPLIANCE_VALIDATION allows us to pass a body to the request. If we didn't use this, then we would get an error.
The problem with this code, is that even though we set this override property, the client completely overrides the GET method and automatically makes it a POST method, so I would get back a 405 Method Not Allowed.
The solution I came up with is to just allow the client to set a header, e.g. X-GET-BODY-OVERRIDE, and then use a #PreMatching filter on the server side to check for this header. If the header is present, then just change the method to a GET
#Provider
#PreMatching
public class GetWithBodyFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext request) throws IOException {
String getOverride = request.getHeaderString("X-GET-BODY-OVERRIDE");
if (getOverride != null && "true".equalsIgnoreCase(getOverride)) {
request.setMethod(HttpMethod.GET);
}
}
}
Then just register the filter with the server side. On the client, you would simply need to add the header
ClientBuilder.newClient()
.target("http://localhost:8080/api/get-body")
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
.request()
.header("X-GET-BODY-OVERRIDE", "True")
.method(HttpMethod.GET, Entity.text("Hello World"));
This solution is good because it takes into account more than just the Jersey client, in regards with being able to send a body in the GET request.
I am getting correct result when invoking method #GET, but as soon as i use #PUT method using URI localhost:8080/MyProject/rest/calculator/23, it is giving error i.e. HTTP Status 405 - Method Not Allowed.
Code is below:
#Path("/calculator")
public class CalcyRest {
#GET
#Path("plain/{name}")
#Produces(MediaType.TEXT_PLAIN)
public String getplain(#PathParam("name") String name){
return "this is plain text ... Hello : "+name;
}
#GET
#Produces(MediaType.TEXT_HTML)
public String getplain(){
return "<html><head><title></title></head><body><h1>this is html</h1></body> </html>";
}
#PUT
#Path("{studentRollNo}")
#Produces(MediaType.TEXT_PLAIN)
public String updateCal(#PathParam("studentRollNo") String strn){
return "updated successfully!";
}
}
First of all, you didn't really ask a question. You are just describing your problem. Here on SO it is very important to know how to ask a question.
Secondly, it would have been a good idea to have posted the URL for the GET request, in order for us to notice some possible subtle mistakes.
Thirdly, please make sure your request URL is good. I was expecting to see something like localhost:8080/MyProject/calculator/23. Why did you put rest inside the URL?
Check your web server configuration. $1 says it is set to reject PUT requests.
I defined a domain model class with a few properties and marked it as a RESTful resource using #Resource following the official Grails guide on Web services. Now, when testing the application (using Ruby's RestClient) I can see that things are working fine. However, after defining an associated Controller that overrides save method (for creating new resource), I've been getting 404 even on just simple GET requests. I defined some test objects using BootStrap so GET should be working.
My controller code looks like this:
class ModelController {
#Transactional
def save(Model model) {
def status = 201
if (model.validate()) {
model.save(flush: true, failOnError: true)
} else {
status = 422
}
render status:status
}
}
Do I still need to do something with the UrlMappings.groovy or is there something wrong with my controller code (all my unit tests for it are passing though)?
Update
I have created a sample project to demonstrate what's happening. Please check my bookstore-demo repository on GitHub. In the repository, I've defined 2 tags, rest-working, and rest-not-working. The first one marks the point where things are still working, and second one, as the name suggests, marks where I've created a controller that causes 404 response. This is pretty much what I've done with my actual project so far, and I'm getting the the same error.
The code looks OK, if you are getting a 404 then it sounds like its not even hitting this Controller. I would open developer console and try capture what URL it is hitting - URL being sent is potentially incorrect. If I am experimenting I tend to put println "1" println "2" and so on between my logics to see where the code is going or did it return it at all meaning it didn't even get there. so maybe if you doubt your code try this tactic between your if statements see which numbers get hit.
Also there is not a lot to go on to try give anything of more useful as feedback, but I would also check out the allowedMethods of this Controller if any defined...
unsure how it is being posted by if you have ..
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
try changing it to
static allowedMethods = [update: "POST", delete: "POST"]
unsure if this is still supported:
static allowedMethods = [save:['POST','GET'],update: "POST", delete: "POST"]
For all the methods refer to:
http://grails.org/doc/latest/ref/Controllers/allowedMethods.html
I'm building a very simple REST API using Jersey, and I've got a warning in my log files that I'm not sure about.
WARNING: A servlet POST request, to
the URI
http://myserver/mycontext/myapi/users/12345?action=delete,
contains form parameters in the
request body but the request body has
been consumed by the servlet or a
servlet filter accessing the request
parameters. Only resource methods
using #FormParam will work as
expected. Resource methods consuming
the request body by other means will
not work as expected.
My webapp only has the Jersey servlet defined, mapped to /myapi/*
How can I stop these warnings?
For me the warning was showing for POST application/x-www-form-urlencoded. And I am using Spring Boot which has an HiddenHttpMethodFilter that does a getParameter before anything else... So I ended up doing this nasty override:
#Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new HiddenHttpMethodFilter() {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if ("POST".equals(request.getMethod())
&& request.getContentType().equals(MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
filterChain.doFilter(request, response);
} else {
super.doFilterInternal(request, response, filterChain);
}
}
};
}
This message is meant to warn developers about the fact that the request entity body has been consumed, thus any other attempts to read the message body will fail.
It is safe to ignore the message or filter it out from the logs:
java.util.logging.Logger jerseyLogger =
java.util.logging.Logger.getLogger(WebComponent.class.getName());
jerseyLogger.setFilter(new Filter() {
#Override
public boolean isLoggable(LogRecord record) {
boolean isLoggable = true;
if (record.getMessage().contains("Only resource methods using #FormParam")) {
isLoggable = false;
}
return isLoggable;
}
});
The following thread describes the warning you are receiving. It sounds as though you might have a filter defined in your web.xml that is processing the request before Jersey does.
Finally got rid of this by making sure I had Content-Type: application/json in my request headers (obviously, on the client side)
I just had my ajax-function in JQuery set to contentType: "application/x-www-form-urlencoded; charset=UTF-8" because with a prior solution (without Jersey) I had some encoding problems. When I removed that the message was gone and everything worked fine.
This warning is the only thing the WebComponent logs, so just turn logging up to ERROR level or turn off logging for this component in your logback.xml or wherever you have logging configured. You don't need to write a custom filter to ignore this specific message since there are no other messages logged from this component.
Source code snippet from org.glassfish.jersey.servlet.WebComponent version 2.14:
if(!form.asMap().isEmpty()) {
containerRequest.setProperty("jersey.config.server.representation.decoded.form", form);
if(LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, LocalizationMessages.FORM_PARAM_CONSUMED(containerRequest.getRequestUri()));
}
}
The localized message that is used for this warning message is:
form.param.consumed=A servlet request to the URI {0} contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
Turn logging off for the WebComponent in your logback.xml like so:
<logger name="org.glassfish.jersey.servlet.WebComponent" level="OFF" additivity="false"/>
Right.
So I've been suffering this issue, and I've been trying to solve it on different ways, but I did't want to change my web.xml settings, just because if I was testing my application with Postman it worked perfect, but when it was being integrated with the webapp it fails with the mentioned issue (A servlet request to the URI {MY_URI} contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.)
So as #clijk mentioned, you only have to set your headers as:
"Content-Type":"application/json"
"charset":"UTF-8"
and voilá, the warning it's gone.
Thanks
In my case I've fixed this error when I've changed the Object Date to String in the method.
Error:
#POST
#Path("/myPath")
#Produces(MediaType.APPLICATION_JSON)
public List<MyObject> myMethod(#FormParam("StartDate") Date date) throws Exception {
Fixed
#POST
#Path("/myPath")
#Produces(MediaType.APPLICATION_JSON)
public List<MyObject> myMethod(#FormParam("StartDate") String date) throws Exception {
Put this to your resource signature. Or find this string in your project someone already use this if #PUT or #POST is used. This should help
import javax.ws.rs.Consumes;
#Consumes(MediaType.APPLICATION_JSON)