Get request parameter with Play Framework? - java

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

Related

How to read the public URL in GWT?

I m new in GWT and I m generating a web application in which i have to create a public URL.
In this public URL i have to pass hashtag(#) and some parameters.
I am finding difficulty in achieving this task.
Extracting the hashtag from the URL.
Extracting the userid from the URL.
My public URL example is :: http://www.xyz.com/#profile?userid=10003
To access the URL in GWT you can use the History.getToken() method. It will give you the entire string that follows the hashtag ("#").
In your case (http://www.xyz.com/#profile?userid=10003) it will return a string "profile?userid=10003". After you have this you can parse it however you want. You can check if it contains("?") and u can split it by "?" or you can get a substring. How you get the information from that is really up to you.
I guess you already have the URL. I'm not that good at Regex, but this should work:
String yourURL = "http://www.xyz.com/#profile?userid=10003";
String[] array = yourURL.split("[\\p{Lower}\\p{Upper}\\p{Punct}}]");
int userID = 0;
for (String string : array) {
if (!string.isEmpty()) {
userID = Integer.valueOf(string);
}
}
System.out.println(userID);
To get the parameters:
String userId = Window.Location.getParameter("userid");
To get the anchor / hash tag:
I don't think there is something, you can parse the URL: look at the methods provided by Window.Location.

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)

Reading request data on RESTlet

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();
}

How can I used named parameters in a messages.properties file?

Is there any way to have message.properties records as follows
message.myMessage=This message is for ${name} in ${location}
as opposed to
message.myMessage = This message is for {0} in {1}
When I am creating the messages, I don't neccessarily know the order / how many parameters are needed, but I am able just pass in several properties by name, and just the correct ones would be used.
After facing the very same question and poking in source code I found a "loop-hole" that makes it possible in a very easy way:
message.myMessage = This message is for {0,,name} in {1,,location}
This approach doesn't eliminate usage of numbers. The reason to use it is to give hints to translation folks.
I am afraid not, parameters are an Object array so there is no way to define names for them. If you always passes in the array of parameter in the same order though you could use them like this:
message.myMessage = This message is for {0} in {1}
message.myNameMessage = This message is for {0}
message.myLocationMessage = This message is for people in {1}
message.myAlternateMessage = The message params are location: {1}; name: {0}
Take a look at ICU4J
It allows for something like this:
message.myMessage=This message is for {name} in {location}.
And it is way more powerful than the simple replacements suggested, because can do locale aware formatting of the parameters (ie: "Subscription expires on: {expirationDate, date, long})
http://icu-project.org/apiref/icu4j/com/ibm/icu/text/MessageFormat.html
Unfortunately the MessageFormat API does not support named parameters, only argument-index:
Patterns and Their Interpretation
MessageFormat uses patterns of the following form:
MessageFormatPattern:
String
MessageFormatPattern FormatElement String
FormatElement:
{ ArgumentIndex }
{ ArgumentIndex , FormatType }
{ ArgumentIndex , FormatType , FormatStyle }
Everything is possible for those who try... I never heard about something like that for Java, but you can write it by yourself.
Please take a look at this example:
public String format(String message, String... arguments) {
for (String argument : arguments) {
String[] keyValue = argument.split("=");
if (keyValue.length != 2)
throw new IllegalArgumentException("Incorrect argument: " + argument);
String placeholder = "${" + keyValue[0] + "}";
if (!message.contains(placeholder))
throw new IllegalArgumentException(keyValue[0] + " does not exists.");
while (message.contains(placeholder))
message = message.replace(placeholder, keyValue[1]);
}
return message;
}
It is not ideal, as you actually would call it with hardcoded string (which is generally bad idea) and you would be forced to use Strings only, but it can be done. The only question is if it is practical.
It is possible using apache commons lang library.
https://commons.apache.org/proper/commons-lang/
Properties messages = ...
Map<String, String> m = new HashMap<>();
m.put("name", "Mithu");
m.put("location", "Dhaka");
StrSubstitutor sub = new StrSubstitutor(m);
String msg = sub.replace(messages.getProperty("message.myMessage"));
// msg = This message is for Mithu in Dhaka

Categories

Resources