How to invoke RESTful services from HTML forms? - forms

We're using Grails for building RESTful services which we'll call from browser clients using HTML forms, the problem is that forms only support GET and POST, so we're not sure how to handle PUT and DELETE.

Grails template tags can help you there:
However, issuing a request with a method other than GET or POST from a regular browser is not possible without some help from Grails. When defining a form you can specify an alternative method such as DELETE:
<g:form controller="book" method="DELETE">
..
</g:form>
Grails will send a hidden parameter called _method, which will be used as the request's HTTP method. Another alternative for changing the method for non-browser clients is to use the X-HTTP-Method-Override to specify the alternative method name.
Via: http://www.grails.org/doc/latest/guide/13.%20Web%20Services.html

Related

How to enable/disable HTTP methods for RESTful Web service?

I'm writing a RESTful Web service.
Technologies that I use:
Eclipse EE Kepler IDE
GlassFish 3 (based on Java 6)
Jersey
JDK v7
When I annotate a Java method with, for example, the #DELETE annotation
I get the following HTTP error (invoked via URI):
HTTP Status 405 - Method Not Allowed
I would like to know how to enable/disable (so that to enable/disable the above HTTP error) those methods (PUT, HEAD, etc.) and at which level it can be done (Glassfish, Web.xml, etc). As well, can you invoke all of those resource methods (annotated with HTTP method type) from either Web browser's URI, within the <form>, or stand-alone client application (non-browser)?
For example, whether or not the following config line on deployment descriptor is present, it makes no difference:
<security-constraint>
<web-resource-collection>
<web-resource-name>RESTfulServiceDrill</web-resource-name>
<url-pattern>/drill/rest/resource/*</url-pattern>
<http-method>DELETE</http-method>
</web-resource-collection>
Of course, one's can disable a specific resource method by throwing an exception from it (and map it to an HTTP error) as the indication of it. That would indicate that the implementation is not available, for example.
So far, only #GET and #POST (on the <form>) resource methods work out, the other annotated methods, such as #POST (via URI), #PUT, #DELETE, #OPTIONS returns the above HTTP error. And this is where my question needs solutions. Why does the mentioned resource methods cause HTTP error when the former two don't?
An example of a resource method:
#DELETE
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.TEXT_PLAIN)
#Path("/getDelete/{value}/{cat}")
public String getDelete(#PathParam("value") String value, #PathParam("cat") String cat){
return value+" : "+cat;
}
Invoking URL:
getDelete
The deployment descriptor is empty, except for the above lines of XML code. So far, I made the app to work by using annotations, no Web.xml (only contains some default values, such as index.jsp files).
Any ideas out there?
To my understanding, You have your REST APIs exposed and you are trying to access it from HTML <form>.Now you are able to access the GET and POST methods(REST APIs) from HTML <form> but not PUT, DELETE and other HTTP methods.
The reason why you get Method Not Allowed exception when you try to access DELETE or PUT or other HTTP methods is, HTML <form> does not support methods other than GET and POST.
Even if you try
<form method="delete"> or <form method="put">
HTML will not understand these methods and consider this as simply <form> (i.e) default form method is GET.
So even you have mentioned method as DELETE or PUT. It is a GET request.
And when the call is made, the jersey container tries to find the requestpath(here"/getDelete/{value}/{cat}") with the specified method(here GET).
Though this path exists,you have mentioned DELETE as acceptable method in your resource(#DELETE annotation says so). But Jersey is looking for GET now.Since it cant find #GET, it returns Method not allowed Exception.
So, how to solve it?
In HTML <form> you cant use HTTP methods other than GET and POST. It is better to have a wrapper in between the REST layer and HTML. So that you can make a POST call from your HTML, then the wrapper handles that call and which in-turns calls the DELETE of REST layer.
And, why POST method is not working from browser is, By default Browser makes a GET call. Have a look at Postman to make REST calls with different Http methods.

Springs: creating a Restful service without annotating the domain classes with #xml tags

I need to create a restful service. I have no access to some classes but need to send the same classes in the result. Is there a way to map the object to xml. I tried using org.springframework.oxm.castor.CastorMarshaller but it gives response with extra tags in the xml like
<bean-property-binding-result field-error-count="0" global-error-count="0" error-count="0">
Is there a way to get it done using castor marshaller? If not can anyone redirect to write page
I solved this issue by using velocity templates as xml templates and returning that xml as response for the call.

RESTful http DELETE method in scala (play 2.0)

I am building app with Play 2.0.
As far as Play form generator won't generate native http "Delete" request method, it should be replaced with either "Get" or "Post".
#form(routes.Application.delete(id), 'class -> "topRight") {
<input type="submit" value="Delete this computer" class="btn danger">
}
According to Play examples "Post" should be used for "delete" purposes. Though using "Get" is much comfortable as form can be replaced with a simple link (especially having a list of those links on a single page)
So is there any reasons to use POST for emulating DELETE?
The reason to use POST for emulating DELETE instead of GET is because some HTTP verbs (aka methods) are deemed to be safe by the HTTP specification. These methods are HEAD, GET, OPTIONS and TRACE. What this means is there should not be any side effects of application state when making requests using these HTTP methods. Logging, caching, or counter increments are not usually considered application state modification unless it is part of the application domain.
The reason to use POST for emulation of DELETE requests instead of directly using DELETE in a web form is because a number of browsers do not support DELETE directly. Many web frameworks that generate form markup with helpers, like Play and Rails, use the trick you refer to to map the request to the corresponding REST-ish action in the code. See HTTP Method Support in Browsers for more information. Please also see this SO question for more information on this topic. According to the W3C latest candidate recommendation for HTML5, the HTML5 FORM element does not support values for the method attribute other than GET or POST. The same is true for the FORM element in HTML 4.01.
For using non - GET or POST methods you should use JavaScript - for an example jQuery $.ajax() and its type setting.
You can also use Play's javascriptRoutes
Most browsers can't do HTTP requests other than GET or POST from HTML forms, so it's generally emulated using a HTTP POST with an override header or a special form variable.
See Doing a HTTP PUT from a browser

GWT Async to URL

I'm using GWT to develop a web app. I'm currently using AJAX calls to retrieve values from the server. I have following queries regarding to AJAX calls:
Assume: I have an app, name of which is: "Application" and the entry point class is: "entry.java"
I know: the application could be invoked as: http://localhost:8080/Application/entry.html
1. I would like to know what what is the output URL given by gwt.getmodulebaseURL()?
Assume: In the same application I have a service called "ServerValuesService" and its corresponding Async. I have corresponding serviceImpl, which has a method called List < String >search(String) at the server side.
I could retrieve the values from the server as well. However,
2. I would like to know what would be the direct URL to access this service? For Instance, I need to obtain the list of values, by just giving a URL (passing value for the String). i.e. I need to access the method search(String) and retrieve the list just by typing a url such as:
http://localhost:8080/Application/entry/serverValuesService?string="hello"
I'm sure the above URL is wrong. I need to know exact conversion between URL and the corresponding service. Is this possible at all?
Thanks in advance!
1) In your case it will give you http://localhost:8080/Application . Application is your modulename.
2) These services are actually HttpServlets and their URL's are defined in the web.xml file. But Google uses POST method to send your variables and takes care of serialization for you, what you are trying to do is send it via GET method which is as far as I know not implemented by Google RemoteServiceServlet.So I would say no its not possible unless you extend these services to work with GET methods yourself but I don't know if that is possible.
Assume: I have an app, name of which is: "Application" and the entry point class is: "entry.java"
I know: the application could be invoked as: http://localhost:8080/Application/entry.html
The url http://localhost:8080/Application/entry.html is called host page url. In this html page you load your GWT module using a script tag:
<!-- This script tag is what actually loads the GWT module. The -->
<!-- 'nocache.js' file (also called a "selection script") is -->
<!-- produced by the GWT compiler in the module output directory -->
<!-- or generated automatically in hosted mode. -->
<script language="javascript" src="calendar/calendar.nocache.js"></script>
So if you put above example in your entry.html, the module will be loaded from http://localhost:8080/Application/calendar/calendar.nocache.js making http://localhost:8080/Application/calendar/ your module base url.
I would like to know what would be the direct URL to access this
service? For Instance, I need to obtain the list of values, by just
giving a URL (passing value for the String). i.e. I need to access the
method search(String) and retrieve the list just by typing a url
GWT RPC use a custom serialization format to encode requests to the RPC Service on server. The RPC service is implemented as a subclass of RemoteServiceServlet on the server. The RemoteServiceServlet handles the http POST requests, de-serializing the request from client and invvoking appropriate service method of sub-class.
So for directly accessing the service you'll need:
1. The service URL
2. Request payload encoded in GWT's custom serialization format
3. Ability to HTTP POST the payload to the Service URL
1 and 3 are easy to acquire. You already know the URL at which your service is mapped in web.xml. And you can do post from any http client or browser plugins like this. The hard-part would be to generate request payload in GWT's custom serialization format. For simple cases, you can generate a request from your application and capture the raw payload from Firebug, Fiddler or similar tool and simply replay it using your http client.

GWT JSONP with Post not Get

I have a web service in the form `http://....../methodName
It returns a jsonp result such as:
methodName(["a":"a", "b":"b"])
GWT provides JsonpRequestBuilder class to parse jsonp.
JsonpRequestBuilder rb = new JsonpRequestBuilder();
rb.setCallbackParam("callback");
rb.requestObject("http://...../methodName", new AsyncCallback<TestJS>(){
...
});
This structure makes a request to url :
"http://...../methodName/?callback=__gwt_jsonp_P0.onSuccess".
My web service returns a callback with methodName not with __gwt_json.....
So gwt could not create a JavaScriptObject from that response.
Also JsonpRequestBuilder works with GET not POST.
How can I achieve those: Sending requests with POST and modifying GWT's default callback name.
JSONP will NOT work with POST. Its not a GWT limitation btw.
JSONP is essentially including a javascript file from your server. So, when you make a JSONP call, a temporary tag is added to the DOM.
Now, a <script> tag can always makes a GET request. That's a browser thing, and GWT cannot do much about it.
If you want to make a cross-domain POST call, you have to chose from one of the following options (and they have nothing to do with GWT)
Use Flash plus a crossdomain.xml that allows cross domain posts
Use Cross Origin Resource Sharing, or CORS. NOTE that this is only supported in modern browsers
Use a proxy server on your domain
Unfortunatly, this isn't how JsonP works. The requests are made by adding a tag to the page, and the results are passed into a function wrapped around the data – in your case, __gwt_jsonp_P0.onSuccess.
The callback name can't be affected, at least while using JsonpRequestBuilder – the system needs to account for the fact that you could send multiple requests out at once, possibly even to different endpoints. A JsonP endpoint that doesn't allow the caller to customize the callback function name is very unusual, and even more odd is an endpoint expecting JsonP calls that expects an impossible POST.
You can implement your own JsonP client side code by using the ScriptElement type, and registering your own global callback to call into your GWT java code.
Look into the API docs for the web service, and see if there is perhaps a better way to communicate with it, perhaps by using a proxy on your own server, avoiding the cross domain issue altogether.