Sparkjava unable to put data into the response body - java

I'm trying to a client (Android) talk to our server which is using sparkjava, but running into the issue that when the client is trying to parse the body of the response response.data with Volley, it's getting that the response body is empty. The client is sending a JsonRequestObject , which will throw a JSONException if the response's body is empty.
Here is our sparkJava controller:
public static String doThis(Request request, Response response) {
response.type("application/json");
// If the request fails validations, then return a 400
if (request.failsValidations()) {
response.status(HTTP_BAD_REQUEST); // 400
response.header("Error", "Bad request");
} else {
response.status(HTTP_SUCCESS); // 200
// Put the response into the data
String responseData = "{//someJson}"
response.header("data", responseData);
response.body(data);
}
return "";
}
I'm setting the same data in the header and body, but when I look at the response received on the client, the data is only in the header and not in the body. So I was thinking that Spark's response.body() method isn't really putting the data into the response being sent back.
Is the way response.body is represented in sparkjava different from how volley views it? Or is there another way to put data into the response body from spark?

You can do it in two ways:
Using a JSON Object
public static Object doThis(Request request, Response response) {
response.type("application/json");
JSONObject jo = new JSONObject();
jo.put("data", "someData");
return jo;
}
Using a string formatted as JSON
public static Object doThis(Request request, Response response) {
response.type("application/json");
return "{\"data\":\"someData\"}";
}
The first one is better IMO because you can modify the JSON object in a much more convenient way (but you have to import org.json.JSONObject).
Then, on the client side, you should treat the data as JSON data type. Hope it helps.

Related

I am using the Interceptor in springboot , but there I am getting the error as

I have to use the interceptor in springboot to to do some processing before & after request gets proceed. But while using it I am getting one error: As of now I just tried to use to pre-handle method and there I am facing this issue.
org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing"
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:160)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:130)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:124)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:131)
I thought there might be some problem in Json conversion so I tried other solutions like Jackson library there also I am facing the same issue.
Here I have to convert the HttpServletRequest to jsonObject but i am getting the mentioned error. When I removed the below logic of BufferedReader to jsonObject conversion and just return true from prehandle method it works properly.
Code:
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
StringBuffer jb = new StringBuffer();
String line = null;
try {
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null)
jb.append(line);
JSONObject obj = new JSONObject(jb.toString());
System.out.println(obj);
} catch (Exception e) {
}
return super.preHandle(request, response, handler);
}
I am getting 400 while testing the above call from postman.
When you read a body from the HttpServletRequest the body is consumed so when it reaches the controller, where you might have mentioned #RequestBody , there will be no data to be received. That's why you are receiving Status Code : 400 Required request body is missing.
In simpler terms body in the request can be read only once.
But If you want to process before the business logic you have to cache that in the interceptor for using it (May be using ThreadLocal) or look into RequestBodyAdviceAdapter

Does a HttpServlet have to respond to a request?

I have several servlets that do things server side. On a few I just encode some unnecessary data and send it back, which seems pointless. Do you have to respond ? What happens when you just say return ? I've done that before and nothing seems to go wrong but I am relatively new to servlets. Are there consequences for simply returning that go above my head ? And what exactly happens when you return;
if(request.getParameter("name").equals("saveusedcards")) {
String sessId = request.getSession().getId();
//encode request with confirmation that cards were successfully updated
if(usersUpdatedCards.get(sessId).isEmpty()){
//no cards were seen
}
boolean success = DataDAO.updateCards(usersUpdatedCards.get(sessId));
if(success){
System.out.println("Data base update successfull!");
String responseMessage = new Gson().toJson("card successfully udpated");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
System.out.println("updated cards response message: "+responseMessage);
response.getWriter().write(responseMessage);
return;
} else {
System.out.println("Data base update failed...");
String responseMessage = new Gson().toJson("card was not successfully updated");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
System.out.println("updated cards response message: "+responseMessage);
response.getWriter().write(responseMessage);
return;
}
}
The servlet must produce an HTTP response for the client, however it is perfectly acceptable to return no content in the response body. When doing so your servlet should make this clear to the client by sending a response code of 204 (no content). Reference: https://httpstatuses.com/204
Here is an example of how you would set the response code from the doGet method. You could do the same from doPost or service methods.
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// Do whatever work you need to do here...
res.setStatus(HttpServletResponse. SC_NO_CONTENT); // This returns a 204
}

How to get the content from Twilio response message

#RequestMapping(value = {"sms"},method = RequestMethod.POST)
public string rplyMessage(HttpServletRequest request, HttpServletResponse response) throws IOException {
Body body = new Body.Builder("Response message").build();
Message sms =
new Message.Builder().body(body).build();
MessagingResponse twiml = new MessagingResponse.Builder().message(sms).build();
response.setContentType("application/xml");
try {
response.getWriter().print(twiml.toXml());
} catch (TwiMLException e) {
e.printStackTrace();
}
}
This is how I handle the twilio response message.I want to get the content from the response message. and i want to store it in the database.How I can get the content from the response message.
Twilio developer evangelist here.
When Twilio makes a request to your application it sends the parameters encoded as application/x-www-form-urlencoded in the body of the POST request.
I've never written Java Spring MVC before, so excuse me if this isn't spot on, but I believe you can then read those parameters out of the body using the #RequestParam annotation.
#RequestMapping(value = {"sms"},method = RequestMethod.POST)
public string rplyMessage(
HttpServletRequest request,
HttpServletResponse response,
#RequestParam("Body") String message,
#RequestParam("From") String from
) throws IOException {
storeMessage(from, message);
// respond to the request
}
The message body and the number that sent it are the parameters "Body" and "From", you can see all the available request parameters here. So, for example with the message, you set the argument to #RequestParam to the name of the parameter, then you set the type and what you want the variable to be called within the method, thus: #RequestParam("Body") String message.
I don't know how you plan to use the database, but that's what I can tell you. You can read more about #RequestParam here and see some Twilio Java and Spring tutorials here.
Let me know if that helps at all.

JAX RS Client: Catch exception message while making a REST call

I'm using ResteasyClient to make a REST client to my another service A. Say, service A throws an exception CustomException with a message : Got Invalid request.
Here is how I am using the Client:
public Response callServiceA(final String query) {
ResteasyClient client = new ResteasyClientBuilder().build();
String link = "abc.com/serviceA";
ResteasyWebTarget target = client.target(link).path("call");
Form form = new Form();
form.param("query", query);
Response response;
try {
String data =
target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
response = Response.ok().entity(data).build();
} catch (Exception e) {
String message = e.getMessage();
e.printStackTrace();
response = Response.serverError().entity(e.getMessage()).build();
} finally{
client.close();
}
return response;
}
However, when I print the stacktrace, I'm unable to find my custom error message. I can just see the message as HTTP 400 Bad Request.
Could you please suggest me how to access the error message?
NOTE: I am able to get the error message when I call the serviceA using the restClient. Hence, I dont think there is an issue with the service.
Don't deserialize the response straight to a String.
String data = ...
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
When you do this (and there is a problem), you just get a client side exception, which doesn't carry information about the response. Instead just get the Response with the overloaded post method
Response response = ...
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE));
Then you can get details from the Response, like the status and such. You can get the body with response.readEntity(String.class). This way you don't need to handle any exceptions. Just handle conditions based on the status.
Do note though that the Response above is an inbound Response, which is different from the outbound Response in your current code. So just make sure not to try and send out an inbound Response.
Also see this answer and it's comments for some design ideas.

PlayFramework Result with Ajax

According to : PlayFramework Document 2.0 & PlayFramework Document 2.1
I know that in play I can return:
Ok()
badRequest()
created()
status()
forbidden()
internalServerError()
TODO
etc...
I would like to send with ajax an response with my information in it. Unfortunatelly play sends only status information, and some kind of object which I do not understand.
Only method ok("Test message") sends status and my message information. Rest of it dosnt work.
How to deal with it?
-- Edit --
I have ajax method:
$.post($("#assignmentsubmitAddress").text(), { 'units' : submittedUnits },
function(response, status, xhr) {
showNotyfication(status, response);
})
When I return ok("test");
In java script variable response I have just String test
When I return badRequest("test"); In java script variable response I have java object. When I print variable response I am getting Object object.
To send back a response in the json format to your client send a ok containing a string :
/**
* Translate a json object into a json string.
*/
public static<T> String objToJson(Object obj)
{
ObjectMapper mapper = new ObjectMapper();
try{
String json = mapper.writeValueAsString(obj);
return json;
}catch(java.io.IOException e){
Logger.error(e.getMessage(), e);
}
return "";
}
public static Result actions()
{
Object objToSendBack = ...
return ok(objToJson(objToSendBack));
}
You can send back wathever you want, including html, but json is more convenient for communicating with javascript functions.
I've figure it out.
I've just changed variable response which is an object to response.responseText.
Now it works.

Categories

Resources