I am using play java for my project(java play ws API) and
private CompletionStage<String> getAuthToken() {
WSRequest request = ws.url(URL);
WSRequest complexRequest = request.setHeader("X-API-Key", X_API_KEY)
.setHeader(CONTENT_TYPE, CONTENT_TYPE_VALUE)
.setHeader(AUTHORIZATION, CLIENT_DETAILS_BASE64_ENCODE);
CompletionStage<WSResponse> responsePromise = complexRequest.post(GRANT_TYPE + "="
+ PASSWORD + "&" + USERNAME + "=" + USERNAME + "&" + PASSWORD + "=" + PASSWORD);
return responsePromise.thenApply(response-> getAuthToken2().toString());
}
private CompletionStage<String> getAuthToken2() {
WSRequest request = ws.url(URL);
WSRequest complexRequest = request.setHeader("X-API-Key", X_API_KEY)
.setHeader(CONTENT_TYPE, CONTENT_TYPE_VALUE)
.setHeader(AUTHORIZATION, CLIENT_DETAILS_BASE64_ENCODE);
CompletionStage<WSResponse> responsePromise = complexRequest.post(GRANT_TYPE + "="
+ PASSWORD + "&" + USERNAME + "=" + USERNAME + "&" + PASSWORD + "=" + PASSWORD);
return responsePromise.thenApply(response-> addIdentity(response.asJson().findValue("access_token").toString()).toString());
}
What is the mistake I am making? How do I make nested requests one after the other one?
I get
java.util.concurrent.CompletableFuture#75c6e852[Not completed]
as the response to my client
You have to use thenCompose to chain multiple http requests. Here is a working sample: for three sites, we will fetch their page and add the status code to a JSON object. At the end, we return that object.
public CompletionStage<Result> getSites() {
ObjectNode hosts = Json.newObject();
return ws.url("https://www.facebook.com").get()
.thenCompose(res -> {
hosts.put("facebook", res.getStatus());
return ws.url("https://www.google.com").get();
})
.thenCompose(res -> {
hosts.put("google", res.getStatus());
return ws.url("https://www.twitter.com").get();
})
.thenApply(res -> {
hosts.put("twitter", res.getStatus());
return ok(hosts);
});
}
Related
Situation:
[![from Postman, JSON returns the data correctly][1]][1]
[1]: https://i.stack.imgur.com/4Kk0J.png
Server side:
Enables the reading of the request body for all routes under /api/articulos.
Router router = Router.router(vertx);
router.route("/api/articulos*").handler(BodyHandler.create());
router.get("/api/articulos/:cantcomp1/:cantcomp2/:tipoprod/:prodpadre").handler(bizArticulo::getOneReadingBarcode);
Business
private static final String SELECT_CBA = "select art.leyenda, $1 :: numeric as cantidad, uni.abreviatura, "
+ "round(((art.precio_costo * (art.utilidad_fraccionado/100)) + art.precio_costo) * ($2),2) as totpagar "
+ "FROM public.articulos art join public.unidades uni on uni.idunidad = art.idunidad "
+ "WHERE (substring(art.codigobarra,1,2) = ($3) and substring(art.codigobarra,3,6) = ($4))";
public void getOneReadingBarcode(RoutingContext routingContext) {
Double cantComprada1 = Double.parseDouble(routingContext.request().getParam("cantcomp1"));
Double cantComprada2 = Double.parseDouble(routingContext.request().getParam("cantcomp2"));
String tipoProducto = routingContext.request().getParam("tipoprod");
String productoPadre = routingContext.request().getParam("prodpadre");
HttpServerResponse response = routingContext.response();
pgClient
.preparedQuery(SELECT_CBA)
.execute(Tuple.of(cantComprada1, cantComprada2, tipoProducto, productoPadre), ar -> {
if (ar.succeeded()) {
RowSet<Row> rows = ar.result(); // return always ONE ARTICLE
List<Articulo> articulos = new ArrayList<>();
rows.forEach(row -> {
articulos.add(fromBarCode(row));
});
response.putHeader("content-type", "application/json; charset=utf-8")
.setStatusCode(200)
.end(Json.encodePrettily(articulos));
} else {
System.out.println("Failure: " + ar.cause().getMessage());
response.putHeader("content-type", "application/json; charset=utf-8")
.end(Json.encodePrettily(ar.cause().getMessage()));
}
});
}
private static Articulo fromBarCode(Row row) {
String leyenda = row.getString("leyenda");
BigDecimal cantComprada = row.getBigDecimal("cantidad");
String abreviatura = row.getString("abreviatura");
BigDecimal total_a_pagar = row.getBigDecimal("totpagar");
Articulo articulo = new Articulo();
articulo.setLeyenda(leyenda);
articulo.setCant_comprada(cantComprada);
articulo.setAbreviatura(abreviatura);
articulo.setTot_a_pagar(total_a_pagar);
return articulo;
}
Client-side
private void validarArticulo() {
switch (txtCodigoBarra.getText().substring(0,2)) {
case "20":
Integer d = Integer.parseInt(txtCodigoBarra.getText().substring(8, 12));
Double decimal = d * 0.001; // convert to kilos
System.out.println(
String.format("%.3f", decimal) + " | " +
String.format("%.3f", decimal) + " | " +
txtCodigoBarra.getText().substring(0, 2) + " | " +
txtCodigoBarra.getText().substring(2, 8)
);
PosAccess
.getCodigoBarra(
decimal,
decimal,
txtCodigoBarra.getText().substring(0, 2),
txtCodigoBarra.getText().substring(2, 8));
case "77":
}
public static ObservableList<Articulo> getCodigoBarra(Double cantComp1, Double cantComp2, String tipoProducto, String productoPadre) {
ObservableList<Articulo> itemsArticulo = FXCollections.observableArrayList();
WebClient client = WebClient.create(Vertx.vertx());
client
.get(PORT, HOST, "/api/conceptos/" + cantComp1 + "/" + cantComp2 + "/" + tipoProducto + "/" + productoPadre)
// .get(PORT, HOST, "/api/conceptos/")
// .setQueryParam("cantcomp1", cantComp1)
// .addQueryParam("cantcomp2", cantComp2)
// .addQueryParam("tipoproducto", tipoProducto)
// .addQueryParam("productopadre", productoPadre)
.send(ar -> {
if (ar.succeeded()) {
HttpResponse<Buffer> response = ar.result();
response.bodyAsJsonArray().forEach(articulo -> {
JsonObject jo = (JsonObject) articulo;
itemsArticulo.add(new Articulo(jo.getString("leyenda"), jo.getDouble("cant_comprada"), jo.getString("abreviatura"), jo.getDouble("tot_a_pagar")));
});
System.out.println("Received response with status code " + response.statusCode());
System.out.println(response.bodyAsJsonArray());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
return itemsArticulo;
}
Ok, that's the code. When scan the barcode I get this error
0,750 | 0,750 | 20 | 021162
oct. 11, 2020 6:33:18 A. M. io.vertx.core.impl.ContextImpl
SEVERE: Unhandled exception
io.vertx.core.json.DecodeException: Failed to decode:Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 2]
at io.vertx.core.json.jackson.JacksonCodec.fromParser(JacksonCodec.java:100)
at io.vertx.core.json.jackson.JacksonCodec.fromBuffer(JacksonCodec.java:67)
at io.vertx.ext.web.codec.impl.BodyCodecImpl.lambda$static$2(BodyCodecImpl.java:51)
at io.vertx.ext.web.client.impl.HttpResponseImpl.bodyAsJsonArray(HttpResponseImpl.java:116)
at consumer.PosAccess.lambda$0(PosAccess.java:45)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 2]
... 22 more
Anyboy can help me?
TIA
Ernesto
You are calling the wrong endpoint (i.e. /api/conceptos/ instead of /api/articulos).
In the screenshot provided in the post, which illustrates a correct response, you are showing a response for url
192.168.0.15:8092/api/articulos/0.75/0.75/20/021162
but in the code you have
client.get(PORT, HOST, "/api/conceptos/" + cantComp1 + "/" + cantComp2 + "/" + tipoProducto + "/" + productoPadre)
According to my experiences, this error message:
io.vertx.core.json.DecodeException: Failed to decode:Unexpected character ('<'
usualy happens when you try to deserialize an api response into a json, but indeed the response is something like:
<html><body><h1>Resource not found</h1></body></html>
or
<html><body><h1>Internal server error</h1></body></html>
and the parsing fails at the first char <
For your case, this happens at response.bodyAsJsonArray() probably.
please make a debug output for the url what you are calling:
String url = "/api/conceptos/" + cantComp1 + "/" + cantComp2 + "/" + tipoProducto + "/" + productoPadre;
I have String Json:
String data = "param:"+"{\"dataFile\": \n" +
"{\"user\": \"asdasdasd\", \n" +
"\"pwd\":\"vasdadsda\", \"email\": \"vasdasdasd#gg.com\" \n" +
"}\n" +
"}";
Then try to send post to API with webview JSON like this:
myWebView.postUrl("url.com", data.getBytes());
from API the json process with "param" key then get the value, but the json get from API is null, any clue ?
I post my data like this. You may also try with this.
String postData = null;
try {
postData = "email=" + URLEncoder.encode(MyApp.getSharedPrefString(StaticData.EMAIL), "UTF-8") + "&password=" + URLEncoder.encode(MyApp.getSharedPrefString(StaticData.PASSWORD), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
webview.postUrl("url.com",postData.getBytes());
Hey guys!
I'm currently trying to create an app that uses the Twitter API to get timelines of users. I'm currently stuck at a specific point! My user has already logged in and I've already received the access token and the token secret. I'm now trying to send a get request to the Twitter server.
My problem is that I'm always getting a 400 bad request error code WITHOUT any kind of message.
I'm using Volley to send the requests - Heres the code
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Response Time: " + error.getNetworkTimeMs() + " ms");
Log.e(TAG, "Code: " + error.networkResponse.statusCode);
Log.e(TAG, "Data: " + new String(error.networkResponse.data));
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
Long tsLong = System.currentTimeMillis() / 1000;
//I receive all the difference parts
String consumerKey = context.getString(R.string.twitter_consumer_key);
String nonce = GenerationHelper.generateNonce();
String signature_method = "HMAC-SHA1";
String timestamp = tsLong.toString();
String token = sTwitterToken;
String version = "1.0";
// I use this list to pass the parameters to the function
// generating the signature
List<String> param= new ArrayList<>();
param.add("screen_name=" + username);
param.add("count=" + count);
param.add("oauth_token" + sTwitterToken);
param.add("oauth_consumer_key=" + consumerKey);
param.add("oauth_nonce=" + nonce);
param.add("oauth_signature_method=" + signature_method);
param.add("oauth_timestamp=" + timestamp);
param.add("oauth_version=" + version);
String signature = GenerationHelper.generateSignature(context, param, "POST", "https://api.twitter.com/1.1/statuses/user_timeline.json");
// I create the header String
StringBuilder paramBuilder = new StringBuilder();
paramBuilder.append("oauth_consumer_key=\"" + consumerKey + "\", ");
paramBuilder.append("oauth_nonce=\"" + nonce + "\", ");
paramBuilder.append("oauth_signature=\"" + signature + "\", ");
paramBuilder.append("oauth_signature_method=\"" + "HMAC-SHA1" + "\", ");
paramBuilder.append("oauth_timestamp=\"" + timestamp + "\", ");
paramBuilder.append("oauth_token=\"" + sTwitterToken + "\", ");
paramBuilder.append("oauth_version=\"" + "1.0" + "\"");
String credentialString = paramBuilder.toString();
Log.d(TAG, credentialString);
params.put("Authorization", "OAuth " + credentialString);
return params;
}
};
My current response is
Code: 400
Data:
If I remove the line adding the authorization data I get the response
Code: 400
Data: {"errors":[{"code":215,"message":"Bad Authentication data."}]}
I'm pretty sure that I don't get rate limited because I'm just sending about 10 requests per 15 minutes.
Does anybody have any idea why I'm having this problem?
String pay= "["
+ "{"
+ "\"internalAssessmentResponseId\" : \"Mer\\/ccclsv__AC1B752E-D079-4BA9-AA4F-46E1F8DDC11F__3048\","
+ "\"responses\":["
+ "{"
+ "\"assessmentCreatedDate\":\"2016-11-25T11:35:54\","
+ "\"responseData\":[],"
+ "\"assessmentId\":\"943\","
+ "}"
+ "],"
+ "\"addtionalInformation\":[],"
+ "\"emailId\":\"lucky#me.com\","
+ "\"salesTeam\" :\"\","
+ "\"demographic\": {"
+ "},"
+ "\"repId\":\"AJMA-OG9OMQ\","
+ "\"assesseeId\":\"AGHA-2D0FVL\","
+ "\"assesseeType\":\"CONTACT\","
+ "\"typeOfResponse\":\"iPad\","
+ "\"userTimeZone\":\"a\""
+ "}"
+ "]";
HttpClient httpclient = new HttpClient();
PostMethod post = new PostMethod("http://signature");
post.setRequestEntity(new StringRequestEntity(pay, "application/json", null));
httpclient.executeMethod(post);
String jsonResponse = post.getResponseBodyAsString();
jsonInsertRes = jsonResponse;
System.out.println("Response in create==>"+jsonResponse);
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch
(IOException e)
{
e.printStackTrace();
}
return jsonString.toString();
}
I am getting wrong response like this
Can not construct instance of org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput, problem: abstract types can only be instantiated with additional type information
at [Source: org.apache.catalina.connector.CoyoteInputStream#11ff00b3; line: 1, column: 1]
You can try sending JSON string as a string form parameter
and then on server read the JSON string value and convert the string to a Java Object(say object of Message.java as for example).
Message msgFromJSON = new ObjectMapper().readValue(JSONString, Message.class);
I have tried few times and it worked fine.
I need to POST data and at the same time redirect to that URL in REST environment. I can do this for normal strings, but the requirement is to POST specific Object.
The way I do it for normal string is -
public Response homePage(#FormParam("username") String username,
#FormParam("passwordhash") String password) {
return Response.ok(PreparePOSTForm(username)).build();
}
private static String PreparePOSTForm(String username)
{
//Set a name for the form
String formID = "PostForm";
String url = "home";
//Build the form using the specified data to be posted.
StringBuilder strForm = new StringBuilder();
strForm.append("<form id=\"" + formID + "\" name=\"" +
formID + "\" action=\"" + url +
"\" method=\"POST\">");
strForm.append("<input type=\"hidden\" name=\"" + "username" +
"\" value=\"" + username + "\">");
strForm.append("</form>");
//Build the JavaScript which will do the Posting operation.
StringBuilder strScript = new StringBuilder();
strScript.append("<script language=\"javascript\">");
strScript.append("var v" + formID + " = document." +
formID + ";");
strScript.append("v" + formID + ".submit();");
strScript.append("</script>");
//Return the form and the script concatenated.
//(The order is important, Form then JavaScript)
return strForm.toString() + strScript.toString();
}
But this method is not sending Objects. I need a work around to send complex Objects. Please help me with this issue.
Thanks in advance.