Reading request data on RESTlet - java

I am trying to create a restful service, using GAE and RESTlet on the server side and jQuery on the client side. Dispite the very poor documentation on RESTlet, I am determined to familiarise myself with a restful framework. However, I can't even get the basic functionality out of it.
The problem I have is that out of GET, POST, PUT and DELETE, only DELETE requests appear to deliver the data part.
The calls are made like this:
function put() {
try {
$.ajax({
url : url,
type : "PUT", //Same for GET, POST and DELETE
data : data,
success : function(data) {
try {
$("#results").text(data);
} catch (e) {
alert(e);
}
}
});
} catch (e) {
alert(e);
}
}
On the server-side I have a resource attached on a router, and it goes like this:
public class TaskResource extends ServerResource
{
String userID = "jada";
#Override
public void doInit()
{
super.doInit();
userID = (String) getRequestAttributes().get("user");
}
#Get
public String toString(String str)
{
return "GET: task of " + userID + " ||| DATA: " + str;
}
#Put
public String putit(String str)
{
return "PUT: task of " + userID + " ||| DATA: " + str;
}
#Post
public String postit(String str)
{
return "POST: task of " + userID + " ||| DATA: " + str;
}
#Delete
public String deleteit(String str)
{
return "DELETE: task of " + userID + " ||| DATA: " + str;
}
}
In the four cases above, as str, GET gets a null argument (understandable), PUT and POST get empty strings and DELETE gets the data actually sent.
I have experimented with changing the type of the arguments (to Representation or Form) and with more specific annotations (e.g #Get("xml")). No success so far.
Any recommendations are welcome.

Recommendation: Use a better-documented ReST framework. They're definitely out there. Jersey, for example, is really easy to get up and running, and it has the benefit of being an implementation of JAX-RS, of which there are several other mature implementations that you can play around with once you learn the API.

So, you are trying to fetch the request entity. I'm not sure if methods marked with #Put or #Post should have the request entity automatically passed in like you are expecting. I'm not sure why it works for DELETE though and not the others. Anyways, try the code below out and see if you get anything. If getEntityAsText() still comes up empty, there is likely something else going on.
Try this out:
#Put
public String putit() {
return this.getRequest().getEntityAsText();
}

Related

Unable to pass Array from Angular 2 typescript to Spring Java

I am trying to pass a String array from my typescript
tmp : Array<string> = [];
So I have a function which takes in this array as a parameter input
passValues(test : Array<string>) {
........
// some method to call post method from service
}
So in service
public passingOfValues( test : Array<string> ) : Observable<Array<string>> {
let headers = new Headers({ 'Content-Type': 'application/json'} );
let options = new RequestOptions({ headers: headers);
let response = this.http.post(this.basePath + this.modulePath + '/getArrayValue', {'test' : test }, options)
.map(this.extractData)
.catch(this.handleError);
return response;
}
But I am getting errors such as System property [org.owasp.esapi.devteam] is not set
And I read on other posts that I have to stringify the array before passing to backend.
Is there a reason why I need to stringify / also can I just pass the raw array?
EDIT 1 :
including backend controller codes
public ResponseEntity<?> getArrayValues( ArrayList<String> test ) {
logger.debug("### Test if array has a size ###" + test.size());
}
Apparently size already shows 0 from here.
EDIT 2 :
While debugging, i realised that the SQL at the back is receiving
say
HOME CHARACTER(20 OCTETS)
does this make any difference?
Like passing of string into octets or do I have to do some conversion?
Sorry if I have alot of questions am also working hard on debugging and learning more about it!
Most of the developers like JSON data as request and it's good practice in RESTful apis. why?
JSON format is {key1: value1, key2: value 2,....}
You are passing
this.http.post(this.basePath + this.modulePath + '/getArrayValue',{'test' : YOUR_ACTUAL_ARRAY})
form the front-end. The httpClient.post(url,body,options?) has url and body as mandatory. How can you get it in back-end? Since you have body only,
public ResponseEntity<?> getArrayValues(#RequestBody List<String> test) {
// codes
}
Key of passed parameter from front-end test and variable which
listens in back-end should be in same name. Otherwise
#RequestBody("KEY_NAME") List<String> any_variable
As you asked from comment, you may have two key value pairs. Eg : { "test" : value1, "tmp": value2}. Assume value1 and value2 both are String array.
this.http.post(this.basePath + this.modulePath + '/getArrayValue',{'myJson' : YOUR_JSON})
There are lot of way(Eg : Gson,ObjectMapper etc). I use another way.
Create a class called TestTmpConverter
class TestTmpConverter{
List<String> test;
List<String> tmp;
//No-argument constructors & Argument constructors
//Getters
}
In controller
public ResponseEntity<?> getArrayValues(#RequestBody List<TestTmpConverter> myJson ) {
List<TestTmpConverter> test=myJson.getTest();
List<TestTmpConverter> tmp=myJson.getTmp();
// Do your work
}
I only showed one way.There are a lot of way to pass data to back-end like #RequestParam, #PathVariable etc. I feel now you get something how you can pass the data.
For your client put your data directly on POST's body:
public passingOfValues( test : Array<string> ) : Observable<Array<string>> {
let headers = new Headers({ 'Content-Type': 'application/json'} );
let options = new RequestOptions({ headers: headers);
let response = this.http.post(this.basePath + this.modulePath + '/getArrayValue',
test, options)
.map(this.extractData)
.catch(this.handleError);
return response;
}
On your REST service use the #RequestBody annotation:
public ResponseEntity<?> getArrayValues(#RequestBody String[] test ) {
logger.debug("### Test if array has a size ###" + test.size());
}

Java : How to extract parameters from Google Dialogflow V2 response

Does anyone know how to extract the parameters returned by the Google dialogflow v2 response? I am able to get the intents and confidence properly as there are high level methods available to do so. But it seems there is no method to get the parameters/list of params. The response contains a google protobuf Struct that has the params. Does anyone know how to extract the parameter names and values from it.
Here is a sample response
query_text: "next friday"
parameters {
fields {
key: "appointmentDate"
value {
struct_value {
fields {
key: "date"
value {
string_value: "2019-05-31T12:00:00+10:00"
}
}
}
}
}
}
all_required_params_present: true
fulfillment_messages {
text {
text: ""
}
}
intent {
name: "projects/dksjdkjsjksd-c824f/agent/intents/89a100c4973a"
display_name: "captureDate"
}
intent_detection_confidence: 1.0
language_code: "en"
It would be something lilke this:
for (Entry<String, Value> entry : queryResult.getParameters().getFieldsMap().entrySet()) {
if (entry.getValue().getKindCase().getNumber() == Value.STRING_VALUE_FIELD_NUMBER) {
log.debug("FOUND PARAM. KEY:" + entry.getKey() + " STRING VALUE: "
+ entry.getValue().getStringValue());
} else if (entry.getValue().getKindCase().getNumber() == Value.STRUCT_VALUE_FIELD_NUMBER) {
log.debug("FOUND PARAM. KEY:" + entry.getKey() + " STRUCT VALUE: "
+ entry.getValue().getStructValue());
}
else if (entry.getValue().getKindCase().getNumber() == Value.NUMBER_VALUE_FIELD_NUMBER) {
log.debug("FOUND PARAM. KEY:" + entry.getKey() + " NUMBER VALUE: "
+ String.valueOf(entry.getValue().getNumberValue()));
}
}
I was too focussed to parse and map the proto buffer to a Java bean. After spending hours and posting a question, a simple thought striked to my mind to find a way to convert the proto buffer to a json. And then it was all simple because I found this API
JsonFormat.printToString(protoMessage)
It sounds simple now but that is all because I changed my problem solving strategy from learning proto buffer and decoding it, to rather use a proto to json convertor and work with json format, which understand much better.

Get request parameter with Play Framework?

I am learning play framework and understand that I can map a request such as /manager/user as:
GET /manage/:user Controllers.Application.some(user:String)
How would I map a request like /play/video?video_id=1sh1?
You have at least two possibilities, let's call them approach1 and approach2.
In the first approach you can declare a routes param with some default value. 0 is good candidate, as it will be easiest to build some condition on top of it. Also it's typesafe, and pre-validates itself. I would recommend this solution at the beginning.
Second approach reads params directly from request as a String so you need to parse it to integer and additionally validate if required.
routes:
GET /approach1 controllers.Application.approach1(video_id: Int ?=0)
GET /approach2 controllers.Application.approach2
actions:
public static Result approach1(int video_id) {
if (video_id == 0) return badRequest("Wrong video ID");
return ok("1: Display video no. " + video_id);
}
public static Result approach2() {
int video_id = 0;
if (form().bindFromRequest().get("video_id") != null) {
try {
video_id = Integer.parseInt(form().bindFromRequest().get("video_id"));
} catch (Exception e) {
Logger.error("int not parsed...");
}
}
if (video_id == 0) return badRequest("Wrong video ID");
return ok("2: Display video no. " + video_id);
}
PS: LOL I just realized that you want to use String identifier... anyway both approaches will be similar :)
I would do it simply using:
GET /play/video Controllers.Application.video(video_id:String)
And at controller you would of course have, something like:
public static Result video(String video_id) {
return ok("We got video id of: " + video_id);
}
Alternatively, you dont have to add video_id:String since play seems to treat parameters as String by default, so it also works like this (at least with newest play):
GET /play/video Controllers.Application.video(video_id)
Typing localhost:9000/play/video?video_id=1sh1 to address bar should now you give view which prints:
We got video id of: 1sh1
To add more parameters is simple, like this:
GET /play/video controllers.Application.video(video_id:String, site:String, page:Integer)
Controller:
public static Result video(String video_id, String site, Integer page) {
return ok("We got video id of: " + video_id + " site: " + site + " page: " + page);
}
Typing localhost:9000/play/video?video_id=1as1&site=www.google.com&page=3 to address bar should now you give view which prints:
We got video id of: 1as1 site: www.google.com page: 3
You're welcome ^^.
I'm not quite sure if I got what you meant if you meant just to map a url to function in controller the answer of biesior is perfect but if you mean submitting a form with get method like
#helper.form(action = routes.YourController.page1()) {
}
and having the form's parameter in the url in the url-rewrited format like
page1/foo/bar instead of page1?param1=foo&param2=bar
There is no way to do that because that's http specs
I do often circumvent this limitation by getting the parameters in the first function in controller and then redirect them to another view just like the following
public static Result page1(){
String param1 = Form.form().bindFromRequest().get("param1");
String param2= Form.form().bindFromRequest().get("param2");
return ( redirect( routes.YourController.page2(param1,param2)));
}
Then have whatever in the page2
public static Result page2(String param1,String param2){
...............
}
And have this in the routes file :
GET page2/:param1/:param2 controllers.YourControllers.page2(param1 : String, param2 : String )
I hope it'd help but I'm not sure that's the best practise
Ok so I just read up the documentation and what I understand is that you need to
GET /play/video Controllers.Application.video()
And then in the controller call the getQueryString of the HttpRequest object
http://www.playframework.com/documentation/api/2.1.0/java/index.html

Returning the JSON representation of a String with Jersey

I'm about to setup a REST-Webservice with Jersey.
At the moment I am a bit confused about the correct representation of Strings or other Value types in JSON.
Here are two snippets:
#GET
#Path("user")
#Produces( MediaType.APPLICATION_JSON)
public User user() {
return new User("reini", "admin");
}
Calling this method in a Browser will display a "good" JSON String like that:
{"name":"reini","role":"admin"}
My second method looks like this:
#GET
#Path("hello/{name}")
#Produces( MediaType.APPLICATION_JSON)
public String hello(#PathParam("name") String name) {
return "Hello " + name + ", it is " + new Date();
}
Calling that method in a Browswer will display a pure String without any JSON-Stuff (Curly Braces etc):
Hello firefox, it is Tue Sep 18 13:52:57 CEST 2012
I want to consume this service with the dojo toolkit. The problem is, that I get an for the second method as soon as I set [handleAs: "json"]-flag. It throws me an error "SyntaxError: Unexpected token H" where "H" is the first letter of the returned string.
So: What is the correct json representation of Strings and other value types and what annotations I have to set for my method to produce these?
You should define a DTO and put your String in that. So you will hava a HelloResp class with one String as attribute. In your method populate that attribute and return.
You can check this Tutorial. Another tutorial.
Firefox is not showing error because, it is not processing your response. Whatever is returned by service is displayed. The toolkit however starts processing the reponse as a JSON but did not a valid JSON (JSON starts with {)
If you are returning a String why do you define it as a type JSON?
Just return it as a plain text (MediaType.TEXT_PLAIN):
#GET
#Path("hello/{name}")
#Produces( MediaType.TEXT_PLAIN)
public String hello(#PathParam("name") String name) {
return "Hello " + name + ", it is " + new Date();
}
You can also return it as:
#GET
#Path("hello/{name}")
#Produces( MediaType.APPLICATION_JSON)
public String hello(#PathParam("name") String name) {
return "\"Hello " + name + ", it is " + new Date()+'"';
}
but it's look very strange for me.
Creating DTO for every object also looks strange just for one String.
Is there any better option?

How do I access POST variables in my controller?

I am making the following AJAX request:
$.post('/route', {
arg1 : 'foo',
arg2 : 'bar'
});
Through the route:
POST /route controllers.Test.readPost()
How do I access these POST variables in the method of my controller?
public static Result readPost() {
return TODO; // read post variables
}
I cannot find a simple way of doing this in the documentation. It only states how to get values from JSON requests.
Use DynamicForm
public static Result getValues(){
DynamicForm requestData = form().bindFromRequest();
String name = requestData.get("name");
String desg = requestData.get("desg");
// etc
return ok("You sent: " + name + ", " + desg);
}
There is also other possibility to construct AJAX query and pass arguments via javascriptRoutes: https://stackoverflow.com/a/11133586/1066240
Of course it will pass the params via URL so it's not suitable for every value, but in many places it will be goot enough for sending POST requests with AJAX. Of course javascriptRoutes create the request with type set in routes file.
BTW: it was better if you wrote which version you are using.
you can use GET with an ajaxRequest. more information can be found here http://www.javascriptkit.com/dhtmltutors/ajaxgetpost.shtml
var mygetrequest=new ajaxRequest()
mygetrequest.onreadystatechange=function(){
if (mygetrequest.readyState==4){
if (mygetrequest.status==200 || window.location.href.indexOf("http")==-1){
document.getElementById("result").innerHTML=mygetrequest.responseText
}
else{
alert("An error has occured making the request")
}
}
}
var namevalue=encodeURIComponent(document.getElementById("name").value)
var agevalue=encodeURIComponent(document.getElementById("age").value)
mygetrequest.open("GET", "basicform.php?name="+namevalue+"&age="+agevalue, true)
mygetrequest.send(null)

Categories

Resources