Parse request parameters without writing wrapper class - jersey

How to handle json requests and parse the request parameters in dropWizard?
#POST
#Path("/test")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public String test(#Context final HttpServletRequest request) {
JSONObject data=new JSONObject();
System.out.println(request);
System.out.println(request.getParameterMap());
System.out.println(">>>>>>>>>");
return "{\"status\":\"ok\"}";
}
I wrote the above code and tried the following request.
curl -XPOST -H "Content-Type: application/json" --data {"field1":"val1", "field2":"val2"} http://localhost:8080/test
But request.getParameterMap() is {}
How to parse the parameters without writing a wrapper class?

Your curl command may need some additional quotes around the data (I'm getting an error without them):
curl -H "Content-type: application/json" -X POST -d '{"field1":"tal1", "field2":"val2"}' http://localhost:8080/test
You are sending a POST request without URL parameters. I'm not sure why you are expecting to see something there.
I don't know which version of dropwizard you are using but I couldn't make the combination of #POST and #Path("/something") annotation to behave when a method is annotated. I'm getting HTTP ERROR 404.
To make it work I have to move the #Path annotation to the resource/class level and leave only the #Post annotation at the method.
#Path("/test")
public class SimpleResource {
#POST
#Consumes(MediaType.APPLICATION_JSON)
public String test(final String data) throws IOException {
System.out.println("And now the request body:");
System.out.println(data);
System.out.println(">>>>>>>>>");
return "{\"status\":\"ok\"}";
}
}
To get the body of the request as String just do as above. Taken from here: How to get full REST request body using Jersey?
The console looks like:
INFO [2016-11-24 15:26:29,290] org.eclipse.jetty.server.Server: Started #3539ms
And now the request body:
{"field1":"tal1", "field2":"val2"}
>>>>>>>>>

Related

Java springboot POST request giving 404

I am trying a POST request in POSTMAN but even though its reaching the tomcat server node, I get following error in my localhost_access.log file
"POST /app/MyService/myControllerMethod HTTP/1.1" 404 1010
My Controller class is something like this :
#Controller("myServicecontroller")
#RequestMapping({"/MyService"})
public class MyServiceController {
#RequestMapping(value = {"myControllerMethod"}, method = {RequestMethod.POST})
public String myControllerMethodBackgroundCallBack(HttpServletRequest httpReq,
#RequestBody String request) {
// rest piece of code
}
}
Now my postman curl I am trying with empty data (tried with some value also) but get above 404 error response
curl --location --request POST 'http://my-ip-address:8080/app/MyService/myControllerMethod' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'My-Header-One: lskdnansdlknalkasndl' \
--header 'My-Header-Two: sadasdsa' \
--data-raw '{}'
What am I doing wrong? (app in above url is my service which works fine in other requests)
Same thing when I try with following code it is able to hit the api 200
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod(url);
postMethod.setRequestBody(requestString);
httpClient.setConnectionTimeout(httpReadTimeOut);
httpClient.executeMethod(postMethod);
I have successfully replicated this issue and found the root cause.
Root Cause
#ResponseBody annotation is missing in myControllerMethodBackgroundCallBack method.
Fix
#RequestMapping(value = {"myControllerMethod"}, method = {RequestMethod.POST})
#ResponseBody
public String myControllerMethodBackgroundCallBack(HttpServletRequest httpReq,
#RequestBody String request) {
// rest piece of code
}
}
Why?
#ResponseBody annotation is required with #Controller annotation and if use #RestController annotation then #ResponseBody annotation is not required.
In Short-
#RestController = #Controller + #ResponseBody
You can read more about #Controller and #RestController here https://medium.com/#akshaypawar911/java-spring-framework-controller-vs-restcontroller-3ef2eb360917

Spring ControllerAdvice how to return Json or html page according to Accept request header?

Now, App can return a cutstom 404 page.
#ControllerAdvice
class GlobalControllerExceptionHandler {
#ResponseStatus(HttpStatus.NOT_FOUND)
#ExceptionHandler(NoHandlerFoundException.class)
public String handle404(WebRequest request) {
return "/exceptions/404";
}
}
And I wonder how should I do, if I want to get a JSON when Accept request header is Accept: application/json, like this:
$> curl -H "Accept: application/json" http://localhost:8080/no-such-page
{"timestamp":"2018-04-11T05:56:03.845+0000","status":404,"error":"Not Found","message":"No message available","path":"/no-such-page"}```

how to send a single String to a RestAPI endpoint using CURL

I have a #RestController with an endpoint that receives a single String :
#RestController
public class ScriptController {
private Logger logger = LoggerFactory.getLogger(ScriptController.class);
public ScriptController(Engine engine) {
this.engine = engine;
}
#RequestMapping(value = "/run", method = RequestMethod.POST)
public Object run(#RequestBody String script){
return engine.run(script);
}
}
when I send a request to this endpoint using CURL :
curl --request POST localhost:9999/run --data-binary "testObj.hi()"
I am not receiving the exact String ("testObj.hi()") in the Controller, instead I receive the following one :
testObj.hi%28%29=
what is the problem?
when I change the method from POST to GET (in both sides) it works! but I want to use POST method.
By default, the request body is URL encoded in HTTP requests, and since there is no content-type header, spring boot doesn't decode the encoded characters.
Specifying Content-Type header will solve the problem, something like this:
curl --request POST localhost:8080/run --data-binary "testObj.hi()" -H 'Content-Type: text/utf-8'
It works in case of GET requests because parameters are expected to be URL encoded in case of GET request and they are decoded by the spring.

In Spring Boot - Can you make request mapping that receives the whole message body without any parsing/intervention?

I need to have a method that does not regard/parse the content of request message, just ... pass it along as input parameter to the #PostMapping method.
Is it possible? Because defining parameters like:
#RequestBody byte[] data
or
#RequestBody String text
tell the framework that it suppose to get some xml/json. and I want it to receive plain text + utf-8 encoding.
Some code to clarify:
#RestController
#RequestMapping(path="/abc", method = RequestMethod.POST)
public class NlpController {
#PostMapping(path="/def", consumes="text/plain; charset: UTF-8", produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> processText(#RequestBody String text)
{
...
return ResponseEntity.ok().body(object);
}
}
Trying also:
#RestController
#RequestMapping(path="/abc", method = RequestMethod.POST)
public class NlpController {
#PostMapping(path="/nlp", consumes=MediaType.APPLICATION_JSON_UTF8_VALUE, produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> process(HttpServletRequest request)
{
....
return ResponseEntity.ok().body(article);
}
}
But I get 406 response...
using curl:
curl -v -s -X POST -H "Content-Type:" -H "Content-Type: application/json; charset: utf-8" --data-binary #article.txt localhost:8080/abc/def/
I think you should inject HttpServletRequest as controller method attribute, then you will have acces to request payload.
#PostMapping(path="/something")
public ResponseEntity<Object> processText(HttpServletRequest request) {
// do something with request
}
More info.
406 Not Acceptable
The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/406
If i understand your question correctly you need to load text file directly as input param in spring boot rest call.
You need to modify your code and curl request , please use fllowing code as referance .
#RequestMapping(value = "/abc", method = RequestMethod.POST)
public String ResponseEntity<Object> processText(#RequestParam("file")
MultipartFile file) {
System.out.println("---------loading file----------");
/// Calculation and your logic
return ResponseEntity.ok().body(article);
}
Curl request :
curl -X POST localhost:8080/abc -F "file=#article.txt"
One more issue i can see in your curl request your mapping is abc and you are calling
localhost:8080/abc/def/
Using #RequestParam for multipartfile is a right way?
If using data in memory following code will work for you
#PostMapping(value = "/abc", consumes = "application/json", produces =
"application/json")
ResponseEntity<Object> processText( #RequestBody String input)
throws JSONException {
//
return ResponseEntity.ok().body(article);
}
Short answer: This is not a job for a full blown framework like spring boot. Better use something like spark that can do this with one liner and without any configurations. At least this is the best answer for my humble causes.
Long answer: I could not make spring boot to receive clean body text from a client, not even after many (failed) attempts to tweak the headers / media / consume flag / ... Guess this just (might) not be possible.

Unsupported Media Type in jersey RESTfull api

I am trying to build a RESTfull API using the Jersey library but it gives me an exception.
Here is my Docs class
#XmlRootElement
#XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
public class Docs {
#XmlElement(name = "field")
public String field;
#XmlValue
public String content;
}
#Path("/update")
public class Update {
#POST
#Path("/xml")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public String createIndexXML(Docs docs)
throws Exception {
System.out.println(docs.content);
return "It works";
}
}
If I try to check it using CURL it throws Error 415 Unsupported Media Type
curl -XPOST "http://localhost:8089/update/xml" -d '<docs>
<field>title</field>
</docs>'
You need to add the content type to your request header. Add -H "Content-Type: application/xml" to yourcurl` call.
I think you're also going to find that there are problems with your annotations on your bean - but that's another issue...
This should work:
curl -H "Content-Type: application/xml"
-X POST -d "<docs><field>title</field></docs>" "http://localhost:8089/update/xml"
You should also try Accept: application/xml; watch out for defining both #Produces and #Consumes! See Using #Consumes and #Produces to Customize Requests and Responses.

Resources