CompletableFuture issue with UUID.randomUUID() - asynchronous

So I decided to start using the CompletableFuture in Java8 and I cannot figure out what wrong with this snippet:
public static void main(String...strings) throws Exception {
final Supplier<User> makeUserSupplier = () -> makeUser();
final Supplier<String> uuidSupplier = () -> makeUUID();
final CompletableFuture<User> futureUser = CompletableFuture.supplyAsync(makeUserSupplier);
final CompletableFuture<String> futureUUID = CompletableFuture.supplyAsync(uuidSupplier);
CompletableFuture.allOf(futureUser, futureUUID)
.thenApplyAsync(aVoid -> {
final User user = futureUser.join();
final String uuid = futureUUID.join();
return "received user + " + user + " and uuid is " + uuid ;
})
.handle((ok, e) -> {
System.out.println("ok----" + ok);
System.out.println("e----" + e);
return null;
});
}
private static User makeUser() throws RuntimeException {
// throw new RuntimeException("lkj");
return new User(1L, "mm", "ll", "kk");
}
private static String makeUUID() throws RuntimeException {
return UUID.randomUUID().toString();
// return "dummy";
}
where the User class is defined as:
#Data
#AllArgsConstructor
public class User {
private Long id;
private String username;
private String password;
private String role;
}
The behavior I get is:
Nothing is printed in my console when I use the UUID.randomUUID().toString() and I get result when I use some random String.
The last breakpoint I am able to reach when debugging is the line when I join the futureUUID final String uuid = futureUUID.join(); and then my program stops with no result.
Can someone please try to explain to me why I am getting this strange behavior when using UUID ?
PS: I just started learning CompletableFuture and thought about parallel Futures, then accidentally came to this.
Best regards.

This has nothing to do with the UUID, except that its generation takes some time and you’re not waiting for the completion.
Since all operations happen in background threads and you’re returning from the main method, the JVM will determine that no non-Daemon thread is running anymore and terminate.
Simply add a wait-for-completion operation:
final Supplier<User> makeUserSupplier = () -> makeUser();
final Supplier<String> uuidSupplier = () -> makeUUID();
final CompletableFuture<User> futureUser = CompletableFuture.supplyAsync(makeUserSupplier);
final CompletableFuture<String> futureUUID = CompletableFuture.supplyAsync(uuidSupplier);
CompletableFuture.allOf(futureUser, futureUUID)
.thenApplyAsync(aVoid -> {
final User user = futureUser.join();
final String uuid = futureUUID.join();
return "received user + " + user + " and uuid is " + uuid ;
})
.handle((ok, e) -> {
System.out.println("ok----" + ok);
System.out.println("e----" + e);
return null;
})
.join(); // wait for completion
Note that in your original code, you were using .allOf(futureUser, futureUser) instead of .allOf(futureUser, futureUUID), so the chained operation might get executed when futureUUID has not completed yet, which could cause a worker thread getting blocked in the futureUUID.join() call.
Your code would be much simpler if you used
final CompletableFuture<User> futureUser = CompletableFuture.supplyAsync(() -> makeUser());
final CompletableFuture<String> futureUUID = CompletableFuture.supplyAsync(() -> makeUUID());
futureUser.thenCombineAsync(futureUUID, (user, uuid) -> {
return "received user + " + user + " and uuid is " + uuid;
})
.handle((ok, e) -> {
System.out.println("ok----" + ok);
System.out.println("e----" + e);
return null;
})
.join(); // wait for completion
which is also immune to the mistake made with allOf, as no join() call is needed within a worker thread.

Related

Requeue the failed record in the kafka topic

I have a use case where the records are to be persisted in table which has foriegn key to itself.
Example:
zObject
{
uid,
name,
parentuid
}
parent uid also present in same table and any object which has non existent parentuid will be failed to persist .
At times the records are placed in the topic such a way that the dependency is not at the head of the list , instead it will be after the dependent records are present
This will cause failure in process the record . I have used the seektocurrenterrorhandler which actually retries the same failed records for the given backoff and it fails since the dependency is not met .
Is there any way where I can requeue the record at the end of the topic so that dependency is met ? If it fails for day 5 times even after enqueue , the records can be pushed to a DLT .
Thanks,
Rajasekhar
There is nothing built in; you can, however, use a custom destination resolver in the DeadLetterPublishingRecoverer to determine which topic to publish to, based on a header in the failed record.
See https://docs.spring.io/spring-kafka/docs/2.6.2/reference/html/#dead-letters
EDIT
#SpringBootApplication
public class So64646996Application {
public static void main(String[] args) {
SpringApplication.run(So64646996Application.class, args);
}
#Bean
public NewTopic topic() {
return TopicBuilder.name("so64646996").partitions(1).replicas(1).build();
}
#Bean
public NewTopic dlt() {
return TopicBuilder.name("so64646996.DLT").partitions(1).replicas(1).build();
}
#Bean
public ErrorHandler eh(KafkaOperations<String, String> template) {
return new SeekToCurrentErrorHandler(new DeadLetterPublishingRecoverer(template,
(rec, ex) -> {
org.apache.kafka.common.header.Header retries = rec.headers().lastHeader("retries");
if (retries == null) {
retries = new RecordHeader("retries", new byte[] { 1 });
rec.headers().add(retries);
}
else {
retries.value()[0]++;
}
return retries.value()[0] > 5
? new TopicPartition("so64646996.DLT", rec.partition())
: new TopicPartition("so64646996", rec.partition());
}), new FixedBackOff(0L, 0L));
}
#KafkaListener(id = "so64646996", topics = "so64646996")
public void listen(String in,
#Header(KafkaHeaders.OFFSET) long offset,
#Header(name = "retries", required = false) byte[] retry) {
System.out.println(in + "#" + offset + ":" + retry[0]);
throw new IllegalStateException();
}
#KafkaListener(id = "so64646996.DLT", topics = "so64646996.DLT")
public void listenDLT(String in,
#Header(KafkaHeaders.OFFSET) long offset,
#Header(name = "retries", required = false) byte[] retry) {
System.out.println("DLT: " + in + "#" + offset + ":" + retry[0]);
}
#Bean
public ApplicationRunner runner(KafkaTemplate<String, String> template) {
return args -> System.out.println(template.send("so64646996", "foo").get(10, TimeUnit.SECONDS)
.getRecordMetadata());
}
}

Unable to create a new Task for progress bar in Java FX

I have created a progress bar in mine Java FXML controller UI and passing the values to it thru executeWSButton. I am creating the new task in createWorker() Method and binding the property value to the progress bar.
The issue is now I am not able to create new Task() in createWorker() method.It was working fine 6 month back and I have resumed the development work . Could you please suggest what could be possible reason here
#FXML
public void executeWSButton(ActionEvent event) {
outputTextScreen.appendText(newLine + " Execution for Process: Started" + newLine);
executeWS.setDisable(true);
progressBar.setProgress(0);
copyWorker = createWorker();
if(testModule != "") {
progressBar.progressProperty().unbind();
progressBar.progressProperty().bind(copyWorker.progressProperty());
new Thread(copyWorker).start();
executeWS.setDisable(false);
}
else {
outputTextScreen.appendText(" Execution for Process: " + Item + " do not have any current TestMethods to Call, Hence stopping the test" + newLine);
}
}
public Task createWorker() {
return new Task() {
#Override
protected Object call() throws Exception {
Invoke_TestNG_Classes ws = new Invoke_TestNG_Classes();
String output = ws.iterateThroughTestCases(inputfile_fp, GIfile_fp, testModule,excelPath);
if(output.contains("Mark atleast"))
{
updateProgress(1.0, 1.0);
outputTextScreen.appendText(
"Please mark atleast one test case with flag as Y in Testcase Execution sheet for "+ Item + newLine);
textOutput.setText("Test Execution Aborted");
return true;
}
while (output.contains("Completed")) {
updateProgress(1.0, 1.0);
// progressBar.setAccessibleText("Completed");
System.out.println(output);
outputTextScreen.appendText("Webservice Execution for Process: " + Item + " Completed" + newLine);
textOutput.setText("Test Execution Completed");
return true;
}
return true;
}
};
}

FirebaseFunctions.getinstance() not finishing

I am using FirebaseFunctions as well as https://github.com/voltrue2/in-app-purchase to validate purchases. I am having trouble sending the data back to my client. In the logs of my functions everything goes well and I get the result I want, but as I understand you have to return a promise in order to get the data back to the client when using Firebase's onCall https trigger. The code for my oncall trigger is here.
var iap = require('in-app-purchase');
var purchaseData;
const receipt = data;
iap.config({
googlePublicKeyPath: 'acualpublickey' ,
googleAccToken: 'actualtoken',
googleRefToken: 'actualtoken',
googleClientID: 'actualID',
googleClientSecret: 'actual seceret',
});
iap.setup()
.then(() => {
console.log("receipt: ", receipt)
return iap.validate(receipt).then(onSuccess).catch(onError);
}).catch((error) => {
console.log("error setup: " + error);
throw error;
});
function onSuccess(validatedData) {
var options = {
ignoreExpired: true // purchaseData will NOT contain exipired subscription items
};
purchaseData = iap.getPurchaseData(validatedData, options);
console.log("PurchseData : ", purchaseData);
console.log("ValidatedData : ", validatedData);
return purchaseData;
}
function onError(error) {
console.log("error onError: " + error);
throw error;
}
the function it is called on to be used is this one
void receiptJSONvalidation(String receipt){
if (receipt != null) {
try {
JSONObject jsonObject = new JSONObject(receipt);
Task<Object> validatedReceipt = validation(jsonObject);
validatedReceipt.addOnCompleteListener(this, new OnCompleteListener<Object>() {
#Override
public void onComplete(#NonNull Task<Object> task) {
if (!task.isSuccessful()) {
Exception e = task.getException();
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
FirebaseFunctionsException.Code code = ffe.getCode();
Object details = ffe.getDetails();
errorAlert("task unsuccessful: " + details.toString());
} else {
errorAlert("Error onComplete: " + e.getLocalizedMessage());
}
// ...
} else{
Gson gson = new Gson();
String taskResult = gson.toJson(task.getResult());
errorAlert("taskResult: " + taskResult);
}
}
});
} catch (JSONException e) {
errorAlert("Error Json: " + e.getLocalizedMessage());
}
} else {
errorAlert("You are not subscribed. Please purchase a subscription.");
}
}
the validation method is this
private Task<Object> validation(JSONObject receipt){
mFunctions = FirebaseFunctions.getInstance();
return mFunctions.getHttpsCallable("receiptValidation").call(receipt)
.continueWith(new Continuation<HttpsCallableResult,Object>() {
public Object then(#NonNull Task<HttpsCallableResult> task) throws Exception {
// This continuation runs on either success or failure, but if the task
// has failed then getResult() will throw an Exception which will be
// propagated down.
Object result = task.getResult().getData();
return result;
}
});
}
When I get to both taskResult and result I am getting null while my logs have the actual data I need. I tried to follow the documentation for these functions yet I still don't get what is needed. Also there seems to be a problem with my app not allowing the firebase function to finish. Sometimes the result pops up null before the function is even over. The function will say it took about 8 sec. Yet the alert pops up in way less time.

Whats wrong with this Async HystrixCommand?

I need to send notifications from time to time, I perform this task asynchronously. I'm using HystrixCommand as below to perform an asynchronous RestTemplate call which is not working:
#HystrixCommand
public Future<String> notify(final Query query) {
return new AsyncResult<String>() {
#Override
public String invoke() {
String result = null;
try {
ResponseEntity<HashMap> restExchange = restTemplate.exchange(url,
HttpMethod.POST,
new HttpEntity<String>(mapper.writeValueAsString(queryMap), httpHeaders),
HashMap.class);
LOGGER.info("Response code from " + url + " = " + restExchange.getStatusCodeValue());
result = ""+ restExchange.getStatusCodeValue();
} catch(Exception e) {
LOGGER.error("Exception while sending notification! Message = " + e.getMessage(), e);
}
return result;
}
};
}
This is what I was trying to do earlier(which didn't work either):
#HystrixCommand
public String notify(final Query query) {
new Thread(new Runnable() {
#Override
public void run() {
try {
ResponseEntity<HashMap> restExchange = restTemplate.exchange(url, HttpMethod.POST,
new HttpEntity<String>(mapper.writeValueAsString(queryMap), httpHeaders), HashMap.class);
LOGGER.info("Response code from " + url + " = " + restExchange.getStatusCodeValue());
} catch (Exception e) {
LOGGER.error("Exception while sending notification! Message = " + e.getMessage(), e);
}
}
}).start();
}
P.S: Reason for adding sleuth to the tags is, performing this in a new Thread does not propagate the headers(baggage-*) so trying this hoping the Hystrix command will do the trick
Is the method notify being called from a method in the same class? If that is the case, try calling the method notify directly from a different class where the notify method's enclosing class is injected as a dependency.
Basically, try doing this:
Instead of this:
When using Runnable you have to wrap them in a trace representation. i.e. TraceRunnable. It's there in the docs - http://cloud.spring.io/spring-cloud-sleuth/spring-cloud-sleuth.html#_runnable_and_callable .
As for why the Hystrix stuff doesn't work - most likely it's related to https://github.com/spring-cloud/spring-cloud-sleuth/issues/612 .

DatabaseIOException When Executing Query "Delete"

Can anybody help telling me what is wrong with my code? I am trying to connect to SQLite database, and executing some queries. when trying to create and open the database, create and insert the table, no exception returned. but when I try to execute delete statement,
DatabaseIOException: File system error (12)
always returned. I don't know the cause of the exception exactly. would you tell me what usually cause this kind of exception? I don't even know when I need to close the database and when I don't need to. this solution also makes me confused.
here is my code:
public class DatabaseManager {
Logger log = new Logger();
Database db;
public DatabaseManager() {
createDatabase();
}
private void createDatabase() {
// Determine if an SDCard is present
boolean sdCardPresent = false;
String root = null;
Enumeration enum = FileSystemRegistry.listRoots();
while (enum.hasMoreElements()) {
root = (String) enum.nextElement();
if(root.equalsIgnoreCase("sdcard/")) {
sdCardPresent = true;
}
}
if(!sdCardPresent) {
alert("This application requires an SD card to be present. Exiting application...");
}
else {
try {
URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
db = DatabaseFactory.openOrCreate(uri);
db.close();
//alert("Database OK!");
} catch (Exception e) {
// TODO Auto-generated catch block
//alert("Exception in createDatabase(): " + e);
}
}
}
private void alert(final String message) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.inform(message);
System.exit(0);
}
});
}
private void createTableTask() {
try {
URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
db = DatabaseFactory.open(uri);
Statement st = db.createStatement("CREATE TABLE IF NOT EXISTS t_task (id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "client TEXT, task TEXT)");
st.prepare();
st.execute();
st.close();
db.close();
//alert("Table Task created!");
} catch (Exception e) {
// TODO: handle exception
//alert("Exception in createTableTask(): " + e);
}
}
private void insertTableTask() {
String[] clients = { "Budi Setiawan", "Dian Kusuma", "Joko Ahmad", "Titi Haryanto", "Wahyu" };
String[] tasks = {
"Penawaran terhadap instalasi server",
"Follow up untuk keperluan produk terbaru",
"Pendekatan untuk membina relasi",
"Penawaran jasa maintenance",
"Penawaran terhadap instalasi database"
};
try {
URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
db = DatabaseFactory.open(uri);
for(int i = 0; i < clients.length; i++) {
Statement st = db.createStatement("INSERT INTO t_task (client, task) VALUES (?, ?)");
st.prepare();
st.bind(1, clients[i]);
st.bind(2, tasks[i]);
st.execute();
st.close();
}
db.close();
} catch (Exception e) {
// TODO: handle exception
//alert("Exception in insertTableTask(): " + e);
}
}
public void loadInitialData() {
createTableTask();
insertTableTask();
}
public Cursor getTasks() {
// TODO Auto-generated method stub
Cursor results = null;
try {
URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
db = DatabaseFactory.open(uri);
Statement st = db.createStatement("SELECT client, task FROM t_task");
st.prepare();
results = st.getCursor();
return results;
} catch (Exception e) {
// TODO: handle exception
//alert("Exception: " + e);
}
return results;
}
public void delete(String string) {
// TODO Auto-generated method stub
try {
URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
db = DatabaseFactory.open(uri);
Statement st = db.createStatement("DELETE FROM t_task WHERE client=?");
st.prepare();
st.bind(1, string);
st.execute();
} catch (Exception e) {
// TODO: handle exception
alert("Exception: " + e);
}
}
}
thank you for your help.
I don't see that you close the statement and close the database after select and delete actions. Most probably you can't open database because it wasn't closed correctly.
Big warning SD card isn't available when user mounted devices to PC as external drive. Some devices are going without SD card preinstalled. DB operations are really slow on 5 OS devices. Your alert method code wan't close db what could be issue to open it after on the next application start.
Warning As #pankar mentioned in comment you should add finally {} where you will close resources for sure. In your current implementation if you get exception in execution you will never close database.
Big improvements You don't need to create and prepare statement every loop. Just do it before for. Do bind and execute every loop. And close statement after for.
Improvements You could keep one opened db during application run cycle. It will save you some line of code and time for opening closing.
Notation It's bad practice to have parameter named like 'string'. I would rename it to something more meaningful.

Resources