How to fetch the value out of VertX Future object - vert.x

I am unable to retrieve value out of the Future object. Below is the code for reference
Future<Configure> conf = getLatestVersion(request);
Configure cc = conf.result();
float previousVersion = cc.getVersionNo();
Here is the implmentation of the getLatestVersion(request)
public Future<Configure> getLatestVersion(Configure request) {
Future<Configure> result = Future.future();
configRepository.getLatestVersionNo(request).setHandler(res -> {
if (res.succeeded()) {
result.complete(res.result());
System.out.println("==result from db =="+res.result());
System.out.println("== getVersionNo ="+res.result().getVersionNo());
} else {
result.fail(res.cause());
}
});
return result;
}
In the SOPs i am able get the values from the result.result() and the result.result().getVersion(), but after returning the result from this method to the above caller i am not able to fetch the values.
What i want to achieve here is i need the Configure pojo data out from the Future<Configure>.

You should be using onComplete() callback (or setHandler() in earlier versions):
Future<Configure> conf = getLatestVersion(request);
conf.onComplete( res -> {
if( res.succeded() ){
Configure cc = res.result();
float previousVersion = cc.getVersionNo();
}
} );

Related

How to pass a value from a synchronous method to asynchronous method within an apex class?

I have made a REST call to a url and need to pass the jsonresponse obtained from the synchronous method to the below asynchronous method.I have used a static variable - strresponse to do the same.But i am getting a null value when i call this value in the asynchronous method.Could this be because asynchronous methods do not remember the value given by a synchronous method? is there any alternate way this could be done?
code below:
public with sharing class myController {
public Static String strResponse ;
#AuraEnabled
public static Map<String, Object> retriveNews(){
HttpRequest httpRequest = new HttpRequest();
httpRequest.setEndpoint('endpoint URL');
httpRequest.setMethod('GET');
try{
Http http = new Http();
HttpResponse httpResponse = http.send(httpRequest);
if(httpResponse.getStatusCode() == 200){
newsController.strResponse = httpResponse.getBody();
} else {
throw new CalloutException(httpResponse.getBody());
}
} catch(Exception ex){
throw ex;
}
Map<String, Object> newsJsonData = new Map<String, Object>();
if(!String.isBlank(newsController.strResponse)){
System.debug('jsonstring:'+newsController.strResponse);
newsJsonData = (Map<String, Object>)JSON.deserializeUntyped(newsController.strResponse);
}
System.debug('jsonstring in retrivenews:'+newsController.strResponse);
if(!newsJsonData.isEmpty()){
return newsJsonData;
} else {
return null;
}
}
#future(callout=true)
public static void insertnews()
{
List<Newsroom__c> nrmlist = new List<Newsroom__c>();
System.debug('jsonstring in insertnews:'+newsController.strResponse);
JSONParser parser = JSON.createParser(newsController.strResponse);
while (parser.nextToken() != null) {
// Start at the array of invoices.
if (parser.getCurrentToken() == JSONToken.START_ARRAY) {
while (parser.nextToken() != null) {
// Advance to the start object marker to
// find next invoice statement object.
if (parser.getCurrentToken() == JSONToken.START_OBJECT) {
objectne nrm = (objectne)parser.readValueAs(objectne.class);
objectne__c nroom = new objectne__c(Author__c = nrm.Author,Description__c = nrm.Description);
String s = JSON.serialize(nrm);
system.debug('Serialized object: ' + s);
nrmlist.add(nroom);
system.debug('list of nrooms:'+ nrmlist);
}
}
}
}
Database.SaveResult[] lsr = Database.insert(nrmlist, false) ;
System.debug(lsr);
}
Error - when newscontroller.insertnews() is called - null string to parser

Flink handling Kafka messages with parsing error

I have some Kafka messages of type InputIoTMessage coming in from Kafka and consumed through FlinkKafkaConsumer as below. I want to add an error field in InputIoTMessage class if there is a NoSuchFieldException. Also, Is this the best practice to handle this types of scenario or we have something more elegant in Java 8 e.g. using Option or Future?
String inputTopic = "sensors";
String outputTopic = "sensors_out";
String consumerGroup = "baeldung";
String address = "kafka:9092";
StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment();
FlinkKafkaConsumer011<InputIoTMessage> flinkKafkaConsumer = createIoTConsumerForTopic(inputTopic, address, consumerGroup);
flinkKafkaConsumer.setStartFromEarliest();
DataStream<InputIoTMessage> stringInputStream = environment.addSource(flinkKafkaConsumer);
System.out.println("IoT Message received :: " );
stringInputStream
.filter((event) -> {
if(event.has("jsonParseError")) {
LOG.warn("JsonParseException was handled: " + event.get("jsonParseError").asText());
return false;
}
return true;
})
.print();
InputIoTMessage.java (has method to check if field exists)
public boolean has(String fieldName) {
boolean isExists;
try {
isExists = fieldName.equalsIgnoreCase(this.getClass().getField(fieldName).getName());
} catch (NoSuchFieldException | SecurityException e) {
Field[] fieldArr = this.getClass().getDeclaredFields();
//Question: how to add "jsonParseError" field to the object here ?
}
return true;
}
The filter function does not modify the input records, maybe you can implement the flatMap function, after modifying the record, output through out.collect
stringInputStream.flatMap(new FlatMapFunction<InputIoTMessage, InputIoTMessage>() {
#Override
public void flatMap(InputIoTMessage input, Collector<InputIoTMessage> out) {
if (!input.has("jsonParseError")) {
InputIoTMessage output = xxxxx;
out.collect(output);
}
}
});

Vert.x: Blocking handler issue

I want to use blocking handler, but still get an error:
java.lang.IllegalStateException: Response has already been written
Here is my code:
Server.java
r.route("/api/details/send/").handler(BodyHandler.create());
r.route("/api/details/send/").handler(ctx-> {
JsonArray ja = ctx.getBodyAsJsonArray();
JsonArray params = new JsonArray();
vertx.executeBlocking(futur -> {
for(int i =0; i<ja.size();i++) {
JsonObject req = new JsonObject();
req.put("QUERY", "INSERT INTO detailsfacture VALUES ('',?,?,?,?,?,?,?)");
req.put("DB", "MYSQL_");
params.add(ja.getJsonObject(i).getValue("typefacture"))
.add(ja.getJsonObject(i).getValue("activites"))
.add(Integer.parseInt(ja.getJsonObject(i).getValue("qte").toString()))
.add(Double.parseDouble(ja.getJsonObject(i).getValue("pu").toString())
.add(ja.getJsonObject(i).getValue("unite"))
.add(Double.parseDouble(ja.getJsonObject(i).getValue("montant").toString())
.add(ja.getJsonObject(i).getValue("codefacture"));
req.put("PARAMS", params);
eb.send("EXECUTE", req, res -> {
if (res.succeeded()) {
params.clear();
ctx.response().putHeader("content-type", "application/json").end(res.result().body().toString());
} else {
ctx.response().putHeader("content-type", "application/json").end(res.cause().getMessage());
}
});
}
String result = "orsys";
futur.complete(result);
},resultat->{
ctx.response().putHeader(HttpHeaders.CONTENT_TYPE, "text/plain");
//resultat.result().toString();
});
});
MySql.java
eb.consumer("MYSQL_EXECUTE_WITH_PARAMS", req->{
try{
JsonObject reqParams = (JsonObject)req.body();
String sql = reqParams.getString("QUERY");
client.getConnection( connection -> {
if (connection.succeeded()) {
try{
SQLConnection con = connection.result();
con.updateWithParams(sql,reqParams.getJsonArray("PARAMS"), query -> {
if(query.succeeded()){
UpdateResult urs = query.result();
req.reply(urs.toJson());
//req.reply(query.result());
}else{
req.fail(24, "Err Request : "+query.cause().getMessage());
}
});
}catch(Exception e){
req.fail(24, "Err Conn Failed : "+e.getMessage());
}
} else {
req.fail(24, "Err No Connection : "+connection.cause().getMessage());
}
});
}catch(Exception e){
req.fail(24, e.getMessage());
}
});
P.S. : When I remove executeBlocking only the first records is registred in my database.
Regards.
You insert entities into detailsfacture in a loop. For each insert you call following:
ctx.response().putHeader("content-type", "application/json").end(res.result().body().toString());
As you can see you call the end(...) method of the response object. Thats where the IllegalStateException comes from. As the documentation states:
Once the response has ended, it cannot be used any more.
So you problem has nothing to do with the executeBlocking.
You should take a look at the write(...) method of HttpServerResponse. For each insert you should call write(...) instead of end(...). But this will only work if you know the complete length of the whole response because you need to set the header Content-length. If you are finished with all inserts you need to call end() to complete the response. Also you should only set the header once and not for each insert.
Now some additional comments. I don't see the need for executeBlocking in your case. Because of the problem with Content-length I recommend to wrap each insert with a Future and compose all of them with CompositeFuture. The Future futur is used the wrong way. The send(...) method of Event bus is not blocking and asynchronous. So the futur.complete(result) is called right after you send all your inserts. Also it's strange that the consumer consumes MYSQL_EXECUTE_WITH_PARAMS and the send sends to EXECUTE.
I tried another solution to get my query like that (?,?,...,?),(?,?,...,?),..,(?,?,...,?).
Here is my code :
public static String getMultipleInsertReq(String table, JsonArray columns,JsonArray data){
JsonObject tab= Tables.Tables_list.getJsonObject(table); // name of table
String sql = "";
if(tab != null){
sql = "INSERT INTO "+table + "( ";
if(columns == null){
columns = tab.getJsonArray("COLS"); //columns from ur database
}
if(columns!=null){
for(int i=0;i<columns.size();i++){
if(i==columns.size()-1){
sql+=columns.getString(i)+") VALUES";
}
else{
sql+=columns.getString(i)+",";
}
}
for(int i =0; i<data.size();i++){
for(int j=0; j<columns.size();j++){
if(j==columns.size()-1 && i!=data.size()-1){
sql+="?),";
}
else if (i==data.size()-1 && j==columns.size()-1){
sql+="?)";
}
else if (j==0){
sql+="(?,";
}
else{
sql+="?,";
}
}
}
return sql;
}
}
return null;
}
Hope it helps.
P.S.: it's only a query builder so you can adapt it depending on your needs.
Regards.

Why am I getting an InvalidCastException with competing Newtonshoft.Json.Linq.[JArray,JObject] with very similar code/data?

This code works fine - returns the single record that matches the REST query:
Popul8TheGrid("http://localhost:28642/api/subdepartments/1/10");
private void Popul8TheGrid(string URIToPass)
{
try
{
dataGridView1.DataSource = GetRESTData(URIToPass);
}
catch (WebException webex)
{
MessageBox.Show("Eek, a mousey-pooh! ({0})", webex.Message);
}
}
private JArray GetRESTData(string uri)
{
var webRequest = (HttpWebRequest) WebRequest.Create(uri);
var webResponse = (HttpWebResponse) webRequest.GetResponse();
var reader = new StreamReader(webResponse.GetResponseStream());
string s = reader.ReadToEnd();
return JsonConvert.DeserializeObject<JArray>(s);
}
However, this code, which also should return a single record:
private const string BASE_URI = "http://localhost:28642/api/";
. . .
string URIToPass = string.Format("{0}deliveryitems/{1}", BASE_URI, numericUpDownDeliveryItemId.Value);
Popul8TheGrid(URIToPass);
...fails, with "InvalidCastException was unhandled ... Message=Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'Newtonsoft.Json.Linq.JArray'".
Why might that be? The data returned from the first (working) snippet comes from an MS Access "database"
The data from the second (failing) snippet is from test data:
public DeliveryItemRepository()
{
// Just some bogus/test data for now
Add(new DeliveryItem
{
Id = 1, InvoiceNumber = "123", UPC_PLU = "456", VendorItemId = "789", PackSize = 1, Description = "Something", Quantity = 5, Cost = 1.25M,
Margin = 0.25M, ListPrice = 1.50M, DepartmentNumber = 42, Subdepartment = "5"
});
. . .
This is the Controller method; it works fine when entering the URI in a browser.
// Enter "http://localhost:28642/api/1"
[Route("api/DeliveryItems/{ID:int}")]
public DeliveryItem GetDeliveryItemById(int ID)
{
return _deliveryItemRepository.GetById(ID);
}
...but why that would matter, I know not...
UPDATE
Interestingly enough (perhaps I'm easily amused), this, OTOH, works:
MessageBox.Show(GetRESTScalarVal("http://localhost:28642/api/deliveries/1"));
. . .
private string GetRESTScalarVal(string uri)
{
var client = new WebClient();
return client.DownloadString(uri);
}
By "works," I mean it returns this:
So DownloadString() will even return an entire json "record" and my use of the word "Scalar" was misleading. Maybe I should have said "Single" instead, although that can be confusing, too, what with the data type of the same appellation.
The question still remains as to how I can populate a datagrid with a single json "record"
UPDATE 2
Oddly enough, if I use a different Controller method to get the one record, it works:
private void GetDeliveryItemById()
{
//string uri = string.Format("deliveryitems/{0}", numericUpDownId.Value);
string uri = string.Format("deliveryitems/{0}/1", numericUpDownId.Value);
Popul8TheGrid(uri);
}
The commented out code is what blows up, whereas the other, with a provided const val of 1, works...kludgy, but it works.
UPDATE 3
Perhaps a clue/related to why it won't work when fetching one, but works otherwise, is this Repository code:
public SiteMapping GetById(int ID)
{
return siteMappings.Find(p => p.Id == ID);
}
public IEnumerable<SiteMapping> GetRange(int ID, int CountToFetch)
{
return siteMappings.Where(i => i.Id >= ID).Take(CountToFetch);
}
If GetById() is called with an ID that exists, it works; if one is passed that doesn't exist, though, it fails with, "InvalidOperationException was unhandled by user code . . . Message=Sequence contains no matching element"
Calling GetRange() works robustly - if passed a bogus pair of vals (no records), it simply shrugs its shoulders, rather than getting the old bulgy eye and screaming maniacally.
Changing it to so (see Simon Whitehead's answere here) works:
public SiteMapping GetById(int ID)
{
var entity = siteMappings.Find(p => p.Id == ID);
return entity == null ? null : entity;
}
So trying to find by a particular ID is fragile; trying to find by ID + Count works just fine. Why, I (still) don't know...
This may be somewhat kludgy, but it works:
private JArray GetRESTData(string uri)
{
try
{
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
var webResponse = (HttpWebResponse)webRequest.GetResponse();
var reader = new StreamReader(webResponse.GetResponseStream());
string s = reader.ReadToEnd();
return JsonConvert.DeserializeObject<JArray>(s);
}
catch // This method crashes if only one json "record" is found - try this:
{
try
{
MessageBox.Show(GetScalarVal(uri));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
return null;
}
private string GetScalarVal(string uri)
{
var client = new WebClient();
return client.DownloadString(uri);
}

Netbeans code completion api

I am attempting to make a Netbeans 7.2 code completion module. I am trying to have this code completion to only show up for only PHP. I am also trying to have the code completion to only show up with specific methods/function ie x() and z().
I am new at this. I followed this tutorial http://platform.netbeans.org/tutorials/nbm-code-completion.html to get a brief understanding of the API.
How can I determine what method/function the code completion is being rendered on?
Let me know if you need additional information.
EDIT
I am trying to make it so the code completion is on the 1st parameter of function x() and z()
UPDATE
This is what I have thus far:
return new AsyncCompletionTask(new AsyncCompletionQuery() {
protected void query(CompletionResultSet completionResultSet, Document document, int caretOffset) {
String filter = null;
int startOffset = caretOffset - 1;
try {
final StyledDocument bDoc = (StyledDocument) document;
final int lineStartOffset = getRowFirstNonWhite(bDoc, caretOffset);
final char[] line = bDoc.getText(lineStartOffset, caretOffset - lineStartOffset).toCharArray();
final int whiteOffset = indexOfWhite(line);
filter = new String(line, whiteOffset + 1, line.length - whiteOffset - 1);
if (whiteOffset > 0) {
startOffset = lineStartOffset + whiteOffset + 1;
} else {
startOffset = lineStartOffset;
}
} catch (BadLocationException ex) {
Exceptions.printStackTrace(ex);
}
if(filter.startsWith("x('") || filter.startsWith("z('"))
{
// This is what I would assume is the first param.
String result = filter.replaceFirst("x('|z('", "");
}
}
}, jtc);