First of all, give thanks for reading my question and try to help me and apologize for my English.
I'm new with Spring and I have this message:
A servlet request to the URI
http://localhost:8080/backend/v1/streetviewer/search-street?url=backend2?busqueda=name%20street&idioma=es-es%26cantidad=10
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 backend send a request to backend2 with one parameter (url), but that url contains 3 parameters. I understand that is reason why say that.
But I was reading that #FormParam is used for POST requests and I'm using #QueryParam.
#GET
#Path(ApiPath.PATH_BACKEND2)
public String getDataFromProdServer(#QueryParam(ApiParam.PARAM_URL) final String externalUrl ) {
return mapService.ServerRequest(externalUrl);
}
How can solve it??
To be said you are actually using JAX-RS Implementation, from backend2 I asume it is a separate service so I suggest you to use Spring Implementations for consuming the API. #RequestMapping/#GetMapping and so..
Coming to the question (With Spring Implementation)
#GetMapping(ApiPath.PATH_BACKEND2)
public String getDataFromProdServer(#RequestParam(ApiParam.PARAM_UR) final String externalUrl) {
return mapService.serverRequest(externalUrl);
}
Related
We have a proxy API set up where we accept any path after our proxy (i.e. /proxy/some/path) and then everything after the proxy path should be forwarded on to another API using RESTeasy (so it would call /some/path in my example).
This is necessary for us for several reasons including avoiding CORS issues and it works most of the time for what we need. However, some routes require query parameters some or all of the time, and because we are handling all routes the same, this causes a RESTeasy error today since the URL gets URL encoded to something like /some/path%3ffilter=value.
Our endpoint today looks like:
#Path("proxy/{someUri : .*}")
#GET
public Response proxyGet(
#PathParam("someUri") String someUri,
#HeaderParam(COOKIE) String cookieHeader,
#Context HttpServletRequest request
) {
return prepareProxyResponse(someUri, cookieHeader, request, null);
}
Our RESTeasy interface looks like:
#GET
#Path("/{requestPath}")
Response proxyGet(
#PathParam("requestPath") String requestPath,
#HeaderParam(COOKIE) String sessionCookie,
#HeaderParam(CONTENT_TYPE) String contentType
);
The code that calls this looks like:
return client.proxyGet(fullPath, cookieHeader, contentTypeHeader);
Prior to understanding this issue, we just took the request URI and added the query string to it so the requestPath above looked like some/path?filter=value which gets mangled. Removing the query string avoids that, however, it also means we cannot pass any query params through.
Is there a way to accept any query params and submit them to the other API using RESTeasy? I know we can break these out where needed to manually specify query params with #QueryParam but since there are many (and more getting added regularly) this will be a lot of effort. I think accomplishing what we are trying to do is not possible based on my research in other questions and the docs, but wanted to double-check before we embarked on a long process to convert. Thanks!
I'd like to create a controller which will return Page object. I will need page Pageable to have with page number and its size (it cannot be larger than 50) and some variables which will be search criteria. If this was a POST request, it could look as follows:
public Page<SomeDto) getDto(#RequestBody #Valid RequestDto requestDto, Page pageRequest)
However, it is a GET request so #RequestBody cannot/shouldn't be used.
Additionally, I would like to have something akin to #Valid so that Spring will automatically reject bad request.
I'm wondering whether:
it is possible to and if so how to implement this and have already created Dto from values taken from URL (#PathVariable or #RequestParam) as if it was POST request which maps body to object.
I'd like to avoid using some kind of that code:
public String updateFoos(#RequestParam Map<String,String> allParams) {}
if what is described in 1st is not possible, what solution would be closest as to meeting those requirements?
You can have a HTTP body (and therefore a #RequestBody) for every HTTP requests no matter what HTTP method is used. However, it is not a good REST API design to use a HTTP body for GET request (cf. https://martinfowler.com/articles/richardsonMaturityModel.html)
You can do bean validation with #PathVariable or #RequestParam arguments, you just have to put the annotation you want next to these 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.
My question is similar to getting blobstore to callback to endpoint method but s/he got no reply. Also I actually wrote my code. I created my callback url as
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
String url = blobstoreService.createUploadUrl("/loadImages");
And then I created my endpoint as
#ApiMethod(name = "loadImages", httpMethod = HttpMethod.POST)
public void loadImages(javax.servlet.http.HttpServletRequest req) {
//…. get blob key etc.
}
Then I get an error on my server when the blobstore makes the callback call:
No handlers matched this URL. (404)
Does anyone know what to pass to blobstoreService.createUploadUrl so it is handled by my endpoint method?
I have also tried changing ”/loadImages” to "/_ah/spi/com.company.package.ApiName.loadImages” so that it looks like the other paths, but that didn’t work either. Then I tried "_ah/api/apiname/1/loadImages”: nothing.
Note: I am not looking for an alternative to the blobstore/endpoint. When I use simple servlet to receive the callback it works. But the servlet just cheapens my otherwise endpoint-only code.
I'm afraid you can only user servlets to handle this type of callback. I've been looking for solution for several hours and found this topic.
In short:
The form must include a file upload field, and the form's enctype must
be set to multipart/form-data. The API ... passes the rewritten request to your application on the
given path as a blob key.
As Endpoints doesn't (as far as I know) accept multipart/form-data as
a valid encoding, this won't work. The error messaging you see is
because the Endpoint is expecting JSON.
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}