Can't POST JSON using Volley - java

I've searched a lot but can't find out what's happening. I wrote many variations of this code and here is the most recent one.
Android code
private static void post(#NonNull String url,
#NonNull Context context,
#NonNull final JSONObject jsonRequest,
#NonNull final ServerConnectionAdapter serverConnectionAdapter){
Log.d(TAG, "post: URL = " + url);
RequestQueue queue = Volley.newRequestQueue(context);
JsonObjectRequest postRequest = new JsonObjectRequest(
Request.Method.POST,
url,
jsonRequest,
serverConnectionAdapter,
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
serverConnectionAdapter.onErrorResponse(null, error);
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<>();
// map.put("user", json.toString());
map.put("user", "{\"id\":-1,\"name\":\"Gustavo Araujo\"}");
return map;
}
};
queue.add(postRequest);
}
Server (Java) code
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doPost");
System.out.println("REQUEST: ");
for (Map.Entry<String, String[]> e : request.getParameterMap().entrySet()){
System.out.print(" ");
System.out.println(e.getKey() + ": " + java.util.Arrays.toString(e.getValue()));
}
System.out.println("end");
}
doPost method output
doPost
REQUEST:
end
I've been starring my screen for so long that I think I can't find where is the error. I did find many examples, with and without the getParams(). I tried both, and didn't change anything.
The ServerConnectionAdapter is an abstract class that I created to unify the response with the error listener. I am sure that it is not the problem because it does work flawlessly with the GETs that I have.
The String url also can't be wrong (otherwise the server wouldn't have been triggered.
The jsonRequest also isn't the problem because I already used null there and didn't change the results at all.
As I said, I've been starring this code for hours, all my assumptions may be completely wrong, that's why I'm asking for help.

The error photo you posted in comment in telling me that your request was successful, there isn't any issue from mobile side. The issue is from server side. Because when you are making the request it's going on server but your server is not returning any proper Json. It's returning nothing that's why you are getting that exception. Android request needs a Json in return but you are server is not returning that.
There is a possibility that the issue can be from app side and the cause for that is that maybe you are not sending the proper parameters to server. But as far as I can see, the main issue is from server side. Because all these exceptions are not handled on server side. Like when the parameters are wrong it should return a json with message telling you that the parameters are wrong.

I was doing it wrong. The way that I wrote the doPost method I was reaching the request parametes, like when you access http://localhost:8080/something?key=value what is not what I intend to do.
I needed to read the body of the request. To do so, in Java, it should be as the code below:
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Get the body of the request
BufferedReader reader = request.getReader();
// Print each line
String line;
while ((line = reader.readLine()) != null){
System.out.println(line);
}
}
Thank you for Zohaib Hassan for trying to help.

Related

Internal server error while connecting to Server in android using volley?

here my function code to post using volley
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL_CHECK_IN,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
int status = jsonObject.getInt("status");
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError response) {
}
}) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
#Override
public Map<String, String> getHeaders () {
Map<String, String> map = new HashMap<String, String>();
map.put("Content-Type", "application/json");
map.put("appid", appids);
map.put("timestamp", timestamps);
map.put("token", tokens);
map.put("signature", signatures);
return map;
}
};
}
I don't know what's wrong with my code, because of 2 days ago everything fine.
and when I tried to debug, error show like this
BasicNetwork.performRequest: Unexpected response code 500 for http://api/presence/check_in
can anyone help me, please? because I'm stuck and need help or reference to solve my error
thank you
HTTP code 500 is Internal Server Error. Read more here. It generally implies that server is not able to process the request and come up with a response. This means that the code for your application might be alright whereas the server might be encountering some issue processing the current request body. I see that you are sending String in your request body. One peculiar thing I noticed with sending String in request body is that, we also need to check if the String is null or not, better to to use .trim() method at the end of your string too, which will delete starting and trailing spaces. Something simple like not escaping single quotes ( ' ) for the field you are trying to insert onto the database at your server might cause this. So server side field validation and best practices like Prepared Statements is also crucial. If you are absolutely sure that your client end [android app] is alright, maybe the server is encountering some issue at the endpoint you are hitting.
Test your api with a rest client like POSTMAN or INSOMNIA to be absolutely sure that your server and api layer is working as intended. Good Luck

How to solve javax.net.ssl.SSLHandshakeException: Connection closed by peer

Am trying to send http request using volley but am receiving error
javax.net.ssl.SSLHandshakeException: Connection closed by peer
I google around and try some suggestions but none solve my problem. please help
Bellow is the code am using
public class volley {
static RequestQueue queue=null;
public static String TAG = "MY_VOLLEY";
volley(final String URL,
final String Text
final Context context
){
helper.log(TAG,"Started Loading");
// Instantiate the RequestQueue.
if(queue==null) {
queue = Volley.newRequestQueue(context);
}
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(
Request.Method.POST, URL, new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
return;
}
}
){
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
try {
params.put("message",Text);
params.put("from",From);
} catch (Exception e) {
helper.log(TAG, "Error, hash map failed");
}
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
};
// Add the request to the RequestQueue.
queue.add(stringRequest);
return;
}
}
In terms of debugging the JSSE is a pain in the ...
Most likely the handshake fails and JSSE most of the time only shows you the final problem, i.e. that the server is closing the connection. Quite often the server is telling you the problem in an TLS alert message but that doesn't show up in the exception message.
If you have Wireshark or something similar installed, the easiest way is to fire up a session and look at the TLS-records (Wireshark shows them quite nicely so it's easy to recognize the error-packet containing the error-code and meaning).
If you don't have that tool, yet, you can activate SSL-debugging and look at the messages on STDOUT. Be warned that they are a bit hard to read if you're unfamiliar with TLS and - since it's a global setting - you should make sure that your tests happens when no other TLS-connection is established, otherwise you get mixed outputs. To enable TLS-handshake debugging, set the system property -Djavax.net.debug=ssl:handshake

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
}

Log jax-ws http request and response

I need to log the full http request and response in a JAX-WS WebService call. For the request I need the request headers and the body and for the response, response headers and body.
After some researching, I've found that I can get this information with the property:
-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
and show the information that I need but it dumps it to the console and I need to store it in the database with an internal request id.
I've tried to implement a handler:
public class LoggingHandler implements SOAPHandler<SOAPMessageContext> {
#Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound) {
System.out.println("SOAP outbound!!!!!");
Map<String, List<String>> responseHeaders = (Map<String, List<String>>) context
.get(SOAPMessageContext.HTTP_RESPONSE_HEADERS);
try {
String headers = getHeaders(responseHeaders);
System.out.println(headers);
String body = getBody(context.getMessage());
System.out.println(body);
} catch (Exception ex) {
// TODO: What do I have to do in this case?
}
} else {
System.out.println("SOAP inbound!!!!!");
Map<String, List<String>> requestHeaders = (Map<String, List<String>>) context
.get(SOAPMessageContext.HTTP_REQUEST_HEADERS);
try {
String headers = getHeaders(requestHeaders);
System.out.println(headers);
String body = getBody(context.getMessage());
System.out.println(body);
} catch (Exception ex) {
// TODO: What do I have to do in this case?
}
}
return true;
}
private String getBody(SOAPMessage message) throws SOAPException, IOException {
OutputStream stream = new ByteArrayOutputStream();
message.writeTo(stream);
return stream.toString();
}
public String getFullHttpRequest(HttpServletRequest request) throws IOException {
InputStream in = request.getInputStream();
String encoding = request.getCharacterEncoding();
encoding = encoding == null ? "UTF-8" : encoding;
String body = IOUtils.toString(in, encoding);
return body;
}
private String getHeaders(Map<String, List<String>> headers) throws IOException {
StringBuffer result = new StringBuffer();
if (headers != null) {
for (Entry<String, List<String>> header : headers.entrySet()) {
if (header.getValue().isEmpty()) {
// I don't think this is legal, but let's just dump it,
// as the point of the dump is to uncover problems.
result.append(header.getValue());
} else {
for (String value : header.getValue()) {
result.append(header.getKey() + ": " + value);
}
}
result.append("\n");
}
}
return result.toString();
}
}
but in this case, I can get the http request headers and body but in the response, I only get the body, http response headers are always empty.
Any idea on how to archieve this? The objective is to be able to store the full http request and response in a database.
Thanks!!
You could also try
-Dcom.sun.xml.ws.transport.http.HttpAdapter.dump=true
I'm assuming you're providing your web service from within a Java EE application server of some sort (and not from a standalone client). You cannot have access to Java EE infrastructure like HttpServletRequest and HttpServletResponse outside of the context of a web/Java EE container.
You could try to get your hands on the actual servlet response object (within a web context) with
HttpServletResponse response = (HttpServletResponse) messageContext.get(SOAPMessageContext.SERVLET_RESPONSE); //messageContext is the SOAPMessageContext
List<String> responseHeaderNames = (List<String>)response.getHeaderNames();
for(String headerName : responseHeaderNames){
//Do whatever you want with it.
}
I seriously doubt that you'll be able to get your hands on the full response headers within a handler though. Your question really intrigued me and I've spent quite some time researching that part. In all the code samples I've seen, Not even the example on the metro site attempt to implement this functionality and I think the reason is simple. As at the point where a handler is invoked, the container may not have enough definitive information to stamp an http header on the outbound message. You might be able to add stuff but that's doubtful as well.

GET request using GWT to retrieve XML data?

Oh hello there, fellow SO members,
I have a web service that returns XML data using a simple get request that goes like this :
http://my-service:8082/qc/getData?paramX=0169&paramY=2
the service returns raw xml in the page according to the parameters' values.
I am trying to retrieve this data from a GET request in GWT using RequestBuilder, Request, etc.
However, the response gives me empty text, a Status code of ZERO (which doesn't mean anything and isn't supposed to happen), and so on.
Here's the simplified code that doesn't work.
public class SimpleXML implements EntryPoint {
public void onModuleLoad() {
this.doGet("http://my-service:8082/qc/getData", "0169", "2");
}
public void doGet(String serviceURL, String paramX, String paramY) {
final String getUrl = serviceURL + "?paramX=" + paramX + "&idTarification=" + paramY;
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, getUrl);
try {
Request response = builder.sendRequest(null, new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
response.getStatusCode(); // Gives me 0 (zero) :(
}
#Override
public void onError(Request request, Throwable exception) {
// ... doesn't matter for this example
}
});
} catch (RequestException e) {
// ... doesn't matter for this example
}
}
}
I don't get why this wouldn't work, since this is REALLY simple, I've seen tutorials and they all show me this way of doing things..
Thanks in advance
The reason is, that browsers do not allow cross-site requests with AJAX (see Same Origin Policy).
This means, that you can only call a service on the same server, same port (using the same protocol) as your HTML page. If you want to perform cross-site requests, you can use JSONP, as explained in http://code.google.com/webtoolkit/doc/latest/tutorial/Xsite.html.

Categories

Resources