Pass an URL as param in RESTful WebServices - java

I'm defining a RESTful WebService in Java.
It takes as input:
an username (for instance, jdoe);
an URL (for instance: https://blablablabla.io/sample?boh=mah).
By using GET method of the HTTP protocol, it should produce a JSON file.
Which is the best way to pass these params?
In this particular case, is there a best practice to follow in order to properly pass an URL as param?

You must first encode it, you can use
URLEncoder.encode("url");

If you want to define an http GET method, then the only way to pass parameters to it is through the URI query string (ie. ?x=y&...).
This is because GET calls can not take in a message body.
If you want to pass in more complicated information, you will need to use POST, PUT, or some other method. Though, if you are actually just getting information (semantically), then you shouldn't use anything but GET.

Also you can use Path parameters
This is example
#Path("/users")
public class UserResorce {
#GET
#Path("/{username}")
#Produces(MediaType.APPLICATION_JSON)
public String getUser(#PathParam("username") String username)){
}
}
The url is http://domain_name/your_application_path/users/username

Related

Spring Boot Controller Multiple parameters (<List> and multipart file) object

Hello i am looking if i can handle with only one RestController method multiple params...
with controllers method it could be done... but i couldnt find project with 2 like that.
#PostMapping(value ="upload")
public upload(#RequestParam MultipartFile file,#RequestParam List<String> myParams ){
some code here ....
return;
}
I am just wondering if is also a good practise ... having two deferent type of objects in same controller and if its possible,,, any idea????
Simple answer: Yes, that's possible.
But as you asked for good practice, here's some context:
It is very helpful to understand how HTTP actually transports data.
If your request uses GET as request method, parameters are added to the URL as a query string. That could look like this: http://example.com/index?param1=value1&param2=value2
In this case, Spring maps the key-value pairs from the query string to your method arguments. But this will only work for text.
If you're using POST, the data is sent inside the request body. How that is encoded depends on the media type of your data. For example, the default media type application/x-www-form-urlencoded would encode the data to the same query string as above.
If you want to upload mixed-type form data like a file/blob along with some textual parameters, your data should be encoded with multipart/form-data.
As long as the request body contains a key-value format, Spring Boot will still be able to distinguish and map the parameters via #RequestParam (If the keys don't differ from your attribute names, you don't even need to assign a name to the value attribute).
I highly recommend you to take a look at the #RequestBody and #RequestPart annotations as i think it often is best practice to use a model class (DTO) for the whole request body (or rather the form, semantically), especially if there are a lot of parameters to process.
You will need to specify the names of the variables.
#PostMapping(value ="upload")
public upload(
#RequestParam(value = "file") MultipartFile file,
#RequestParam(value = "myParams") List<String> myParams
){
some code here ....
return;
}

Find out which endpoint sent a REST call

I'm trying to create a visualisation of REST calls among several internal and external services/servers. I'd like to know which endpoint called which other endpoint. I figured that the only way to do this is to do this on the caller side, because the receiver does not have any information about the caller endpoint.
Here's my thinking:
I create an object like RestTemplate and call the method.
I create an Interceptor or something like that, which will extract the information from the RestTemplate.
My problem is that I'm not sure how to find out which REST endpoint called the RestTemplate method. The RestTemplate (or other similar object) call could be called in nested methods, so for example the endpoint could invoke a private method, which then calls the external service itself.
Is there any way how to get this information? Or am I maybe just thinking too hard and there is an easier way to do this?
Example:
#GetMapping("/hello")
public String hello() {
methodThatCallsOtherEndpoint("something.com/weather"); // this method inside itself calls an endpoint
logRestCall("localhost:8000/hello", "something.com/weather"); // how do I do this automatically without having to type it myself?
return "hello";
}
Thanks for any help.
If these services/servers have a static IP you can possibly, tag them by their IP address?
You can use Spring Sleuth to trace the relationship between different REST calls.

explicitly get post parameter or query parameter in controller method

I am using the #RequestParam annotation to instruct Spring MVC to inject a "web request parameter" (as the Javadoc calls them) into a method call in my code:
#RequestMapping(path="/signup-submit", method=RequestMethod.POST)
public String signupSubmit(#RequestParam(value="originURL", required=true) String originURL ...) {
...
I am bothered by the fact that this annotation apparently works both for POST parameters and for URL query parameters. I.e. looking at the above code it is not possible to say whether the originURL is a POST body parameter or is a URL query parameter. Is there an annotation I can use to explicitly get it from either one or the other?
This is why I also place "web request parameter" in quotation marks as I don't think this is a technical term and I guess it is used in the loose sense of "some parameter either passed in the POST method body or as a query parameter in the URL".
Contrary to what cularis said there can be both in the parameter map.
The best way I see is to proxy the parameterMap and for each parameter retrieval check if queryString contains "&?=".
Note that parameterName needs to be URL encoded before this check can be made, as Qerub pointed out.
That saves you the parsing and still gives you only URL parameters.
The way can be getting query string..
public List<Topic> getTopics(HttpServletRequest req) {
String queryString = req.getQueryString();
.....
About "Web-Request-Parameter" (#RequestHeader), you are right as it consists of both params i.e. either are part of query or a part of request body.
Not the exact solution to your problem. But seems like there's an easy hack for it. You can use #RequestBody. This only looks for request body. If param is not found in request body, you can be sure that it is from request param.

Jersey mthod argument without annotations

In RESTful web services written using Jersey, I know I can access path parameters and query string parameters using #PathParam and #QueryParam annotaions. But in a web service written by someone else I saw a method like below.
#POST
#Path("/sms/receive")
#Consumes("application/json")
#Produces("application/json")
public Response smsReceive(String jsonBody) {
//Code here...
}
There is no #PathParam or #QueryParamannotation before the argument jsonBody.
Can anybody explaing what this argument means and how to set value for it when calling this service.
Can I use multiple parameters without annotations?
Thanks.
The service above does not handle query or path parameters at all.
It #Consumes JSON input. That's what the method's parameter jsonBody is referring to.
If someone would want to instruct this service he would add a json payload to the http request which the service (in this case) receives as a simple String. The String then needs to be parsed.
Of course you can combine Path/Query Parameters with JSON Payloads.

Passing a JSONObject as a parameter on Spring MVC

I wish to implement a REST service using Spring MVC where I pass in the following object at the URL "/url/lookup/{jsonparm}":
{"url":"http://bubba.com/foo/bar", "max_hops":3}
I tried the following:
#RequestMapping(value = "/url/lookup/{jsonparam}", method = RequestMethod.GET)
#ResponseBody
public String urlLookup(#PathVariable("jsonparam") String jsonparam) {
// just to see if I can get the parms
logger.debug("urlLookup get request : " + jsonparam.toString());
JSONObject resp = new JSONObject();
return resp.toString(); // return an empty JSONObject for now
}
So I invoke this by calling
http://localhost:8080/v1/wsp/url/lookup/%7B%22max_hops%22%3A3%2C%22url%22%3A%22http%3A%2F%2Fbubba.com%2Ffoo%2Fbar%22%7D
No luck see the following in my Jetty log:
WARNING: No mapping found for HTTP request with URI [/v1/wsp/url/lookup/{"max_hops":3,"url":"http://bubba.com/foo/bar"}] in DispatcherServlet with name 'rest'
Notes:
the url prefix localhost:8080/v1/wsp/ is correct and my Servlet and Request Mapping are also correct
I have updated the question to use a #PathVariable as one of the responders suggested
Thanks.
You're confusing GET and POST methods.
Either:
Use POST method and actually post the JSON contents to the controller. You can debug this using any REST client, eg. Advanced Rest Client for Chrome.
Use GET method (as you are currently). But you have to pass the JSON value as an actual parameter called jsonparam. So, your example should change to:
http://localhost:8080/v1/wsp/url/lookup/jsonparam=%7B%22max_hops%22%3A3%2C%22url%22%3A%22http%3A%2F%2Fbubba.com%2Ffoo%2Fbar%22%7D
The latter is less common.
Edit:
On second look at your URL, I suspect you're confusing two Spring annotations:
#PathVariable("jsonparam") and:
#RequestParam("jsonparam")
You're using #RequestParam while your URL indicates need for #PathVariable.
Edit2:
However, as can be read here: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-uri-templates the path variable can be passed a value of any simple type. I believe JSON isn't one of them, hence your problems.
I would strongly recommend using POST for interchanging JSON values. However, if that is not an option, I would recommend sticking with GET method, #RequestParam for accessing parameter value, and passing the JSON value like in the corrected example above.
You should use #PathVariable instead of #RequestParam:
public String urlLookup(#PathVariable("jsonparam") String jsonparam){
}
because you have #RequestMapping(value = "/url/lookup/{jasonparam}"
And you have a typo in your #RequestMapping value. It should be /url/lookup/{jsonparam} instead of {jasonparam}

Categories

Resources