Performing Asynchronous operations on Vaadin UI - spring-boot

I have a Spring Boot project with Vaadin integration (v14). I want my application to do some background operation and represent the results on the Vaadin-based frontend. For this I have a view which is a Polymer template generated with Vaadin Designer (.js) and connected to a Java companion class. To this view I've just simply added a button initialized with the following listener:
_btnMyTriggerButton.addClickListener(event -> {
CompletableFuture<Void> c = CompletableFuture.supplyAsync(() -> {
for (int i = 0; i < 5; i++)
{
try
{
System.out.println("Waiting");
Thread.sleep(1000);
UI.getCurrent().access(() -> {
Notification.show("Waiting");
});
}
catch (InterruptedException e)
{
}
}
return "Waiting over. Greet!";
}).thenAccept(s -> {
System.out.println(s);
UI.getCurrent().access(() -> {
Notification.show(s);
});
});
I'm trying to access the UI as the documentation says. However when this is being executed it only reaches the first "Waiting", then stops. If I remove the UI interaction (Notification.show()) the output is printed to the backend as desired, but not when attempting do any interaction on the UI..
The structure of my java companion class is the following:
#Tag("my-view")
#JsModule("./my-view.js")
#Route("")
#Push(PushMode.AUTOMATIC)
public class MyView extends PolymerTemplate<MyView.MyModel>
{
#Id("trigger-button")
private Button _btnMyTriggerButton;
MyView() {
// listener initialization code described above
}
public interface MyModel extends TemplateModel
{
}
}
Do I miss something to achieve asynchronous behavior on this webpage?
Any help is appreciated.

The problem in this case is that the first callback terminates with a NullPointerException because UI.getCurrent() returns null when it's run from a background thread. CompletableFuture will just ignore the exception unless you explicitly handle it (e.g. using handle instead of thenAccept) or block on the result.
You can fix this by adding UI ui = UI.getCurrent(); in the beginning of the click listener and then referencing ui in both the supplyAsync and thenAccept callbacks instead of using UI.getCurrent() there.

Related

AEM 6.3 Set up PageEvent Handler/Listener

Im currently working on setting up a event handler for page creations and deletions on aem to then call one of our vendors API.
Ive been basing my work on a module we already have that listens to replication events.
So far i was able to reproduce that behavior on my module and trigger the code upon replications. However, i only need the calls to the API on Page Publications and deletions.
Ive been trying to find how to diferentiate between replications and page deletions and activations.
So far, it seems that AEM handles crx replications and page publications as the same type of event "type= ACTIVATION".
If i delete a page, it does set the type as "DELETE" so i can work with that to call the API but for the page publications im lost since as i mentioned, AEM looks like it handles CRX replications and pages publications as the same type.
After some research, i found the PageEvent API and I tried to set up a Page Event Listener but it is not getting triggered upon publications or deletions of pages, so im not sure that if what im trying to do its possible or maybe my componet is located on a wrong part of the project to listen for Page Events.
Thanks beforehand
This below code works fine to detect page deletion event :
#Component(
service = {
EventHandler.class,
JobConsumer.class
},
immediate = true,
configurationPolicy = ConfigurationPolicy.OPTIONAL,
property = {
"event.topics=" + PageEvent.EVENT_TOPIC,
JobConsumer.PROPERTY_TOPICS + "=" + "aem/custom/event"
}
)
public class CustomEventHandler implements EventHandler, JobConsumer {
#Override
public void handleEvent(Event event) {
PageEvent pageEvent = PageEvent.fromEvent(event);
Map<String, Object> properties = new HashMap<>();
properties.put("pageEvent", pageEvent);
jobManager.addJob("aem/custom/event", properties);
}
#Override
public JobResult process(Job job) {
PageEvent pageEvent = (PageEvent) job.getProperty("pageEvent");
try {
if (pageEvent != null && pageEvent.isLocal()) {
Iterator<PageModification> modificationsIterator = pageEvent.getModifications();
while (modificationsIterator.hasNext()) {
PageModification modification = modificationsIterator.next();
if (PageModification.ModificationType.DELETED.equals(modification.getType())) {
// Your logic
}
}
}
} catch (Exception e) {
logger.error("Error : ", e);
}
return JobResult.OK;
}
}

Rendering the Google Recaptcha in Android Studio 3

I am using Android Studio 3
I am following this article to learn how to use Google Recaptcha in Android Studio.
Installed the package using this: implementation 'com.google.android.gms:play-services-safetynet:12.0.1'
API keys are also registered.
I saw there is onClick event handler but where is it mentioned about rendering the recaptcha?
Update 1
When I wrote the button click code as mentioned in the link...I got a complication error: inconvertible types cannot cast anonymous android.view.view.onclicklistener to java.util.concurrent.executor
Code as asked in comment
btn_Login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
SafetyNet.getClient(this).verifyWithRecaptcha("")
.addOnSuccessListener((Executor) this,
new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
#Override
public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
// Indicates communication with reCAPTCHA service was
// successful.
String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
// Validate the user response token using the
// reCAPTCHA siteverify API.
}
}
})
.addOnFailureListener((Executor) this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ApiException) {
// An error occurred when communicating with the
// reCAPTCHA service. Refer to the status code to
// handle the error appropriately.
ApiException apiException = (ApiException) e;
int statusCode = apiException.getStatusCode();
} else {
}
}
});
}
});
I used below code and everything is work fine now.
Make sure to implement Executor in the activity
btn_Login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
SafetyNet.getClient(Activity.this).verifyWithRecaptcha("")
.addOnSuccessListener((Activity) MyActivity.this,
new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
#Override
public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
// Indicates communication with reCAPTCHA service was
// successful.
String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
// Validate the user response token using the
// reCAPTCHA siteverify API.
}
}
})
.addOnFailureListener((Activity) MyActivity.this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ApiException) {
// An error occurred when communicating with the
// reCAPTCHA service. Refer to the status code to
// handle the error appropriately.
ApiException apiException = (ApiException) e;
int statusCode = apiException.getStatusCode();
} else {
}
}
});
}
});
According to the article, in your button click handler you must call the method SafetyNet.getClient(this).verifyWithRecaptcha(...) to show reCAPTCHA and handle success or error. Passing this, you give the SDK handle to your current view which should be shown after solving reCAPTCHA. Most probably the rendering will be done by the SDK itself given that it’s a part of the OS. And most probably it will be full-screen in a separate top-level view blocking access to your app before solving the riddle.
You should try to implement it in your app as described in the article and see how it goes. Then you can ask a more specific question.
EDIT: You combined 2 techniques in your code: copy-pasting the code from Google and implementing anonymous class from it. So the problem you asked in the comment is that using (Executor) this in line 5 refers now not to your View (as it was there in the original tutorial) but to the instance of the anonymous interface implementation new View.OnClickListener() that you created. Ypu can refer to this answer to see how it can be implemented not interfering with already complex reCAPTCHA code.

Start then Stop Windows Service very fast, the OnStop method did not call

I am doing a windows service (call it SampleService), every is fine. When I started then stopped service through Windows Service Management Tool (service.msc), it run properly.
But my service will be request Start and Stop by another application. So I will not use Windows Service Management Tool in this case.
This is my service implement.
using System.ServiceProcess;
public partial class SampleService : ServiceBase
{
public SampleService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.WriteLog("OnStart");
// Doing start service logic down here
// Some service logic like create some files.
// Or just leave it empty like a brand new Windows Service.
}
protected override void OnStop()
{
this.WriteLog("OnStop");
// Doing clean service logic down here.
// Some service logic like: delete files.
// Or just leave it empty like a brand new Windows Service.
}
static readonly object synObject = new object();
public void WriteLog(string message)
{
if (string.IsNullOrEmpty(message))
{
return;
}
// Write log.
lock (synObject)
{
using (var wr = new StreamWriter(#"C:\logfile.txt", true))
{
wr.WriteLine(DateTime.Now + "-" + message);
}
}
}
}
And this is code logic use to Start and Stop service inside my another application. I can not modify this another application. The bellow source code simulate what happen.
class Program
{
static void Main(string[] args)
{
ServiceController sc = new ServiceController("SampleService");
// start service
sc.Start();
// doing some logic cost deltaTime or just stand by in deltaTime.
Thread.Sleep(deltaTime);
try
{
// stop service first time, nothing happen.
sc.Stop();
}
catch
{
}
try
{
// stop service second times, by dump people or apllication.
sc.Stop();
}
catch
{
// It got an exception here: "The service cannot accept control messages at this time".
// But the service did stopped.
}
}
}
The problem is:"When deltaTime is too short (bellow 3000ms with empty OnStart(), OnStop()), Service will stop incorrectly. The output log OnStop will never show up, that mean OnStop method did not called.
My service will doing clean up work in OnStop (like delete some file), but if it not be called, these files still there.
I cannot change logic of another application but I can change SampleService.
I want to ask:
Is this an Windows Service base issue and I cant do anything with it?
What ever it is, can I do clean up some where else?
Thank you!

Start specific view of Gluon App from a notification

I set up an alarm to show a corresponding Notification. The PendingIntent of the Notification is used to start the Gluon App main class. To show a View other than the homeView, I call switchView(otherView) in the postInit method. OtherView is shown, but without AppBar. While it's possible to make the AppBar appear, I wonder if this is the right approach.
#Override
public void postInit(Scene scene) {
// additional setUp logic
boolean showReadingView = (boolean) PlatformProvider.getPlatform().getLaunchIntentExtra("showReadingView", false);
if (showReadingView) {
switchView(READING_VIEW);
}
}
When triggering anything related to the JavaFX thread from another thread, we have to use Platform.runLater().
Yours is a clear case of this situation: the Android thread is calling some pending intent, and as a result, the app is started again.
This should be done:
#Override
public void postInit(Scene scene) {
// additional setUp logic
boolean showReadingView = (boolean) PlatformProvider.getPlatform().getLaunchIntentExtra("showReadingView", false);
if (showReadingView) {
Platform.runLater(() -> switchView(READING_VIEW));
}
}

JavaFX Repeater

I want to have something like a TimerTask in JavaFX.
I have a order of Functions, this Functions should be repeated every 1/2 Second maybe every 1/4 Second.
This Functions have some effects for a GUI Component in JavaFX.
Can you give me an TimerTask (JavaFX) example ? I can not use Timer Task, becouse the Compiler said this:
Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:237)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:398)
at javafx.scene.Parent$1.onProposedChange(Parent.java:245)
at com.sun.javafx.collections.VetoableObservableList.clear(VetoableObservableList.java:146)
at com.sun.javafx.charts.Legend$1.onChanged(Legend.java:55)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:134)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
at com.sun.javafx.collections.ObservableListWrapper.callObservers(ObservableListWrapper.java:97)
at com.sun.javafx.collections.ObservableListWrapper.clear(ObservableListWrapper.java:184)
at javafx.scene.chart.AreaChart.updateLegend(AreaChart.java:420)
at javafx.scene.chart.XYChart$2.onChanged(XYChart.java:96)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:134)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
at com.sun.javafx.collections.ObservableListWrapper.callObservers(ObservableListWrapper.java:97)
at com.sun.javafx.collections.ObservableListWrapper.removeFromList(ObservableListWrapper.java:383)
at com.sun.javafx.collections.ObservableListWrapper.removeAll(ObservableListWrapper.java:271)
at de.sick.suit.framework.control.fx.HistogramChart.deleteData(HistogramChart.java:170)
at de.sick.suit.framework.samples.ImageHistogram.run(ImageHistogram.java:200)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Thank you for your help!
You can use a ScheduledService. The example from the javadoc:
you may want to ping a server on a regular basis to see if there are any updates. Such as ScheduledService might be implemented like this:
ScheduledService<Document> svc = new ScheduledService<>(Duration.seconds(1)) {
protected Task<Document> createTask() {
return new Task<Document>() {
protected Document call() {
// Connect to a Server
// Get the XML document
// Parse it into a document
return document;
}
}
// TIMER
Timeline line = new Timeline(new KeyFrame(Duration.seconds(0.2), new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent arg0)
{
sek++;
puls(imgHisto, startingArea);
System.out.println(" Sek: " + sek);
}
}));
line.setCycleCount(Animation.INDEFINITE);
line.play();
I handeld the Problem with a TimeLine. This works very fine for my example!
You need to provide more Code, but as of now I think you are not updating the UI properly. If you are in another Thread (which you seem to be if you are using a Task), whenever you want to update the UI you need to use
Platform.runLater();
Your Stacktrace indicates this.
You were updating GUI component outside the JavaFX application thread.
Try something like this
Platform.runLater(new Runnable(){
#Override
public void run(){
//update GUI here
}
});

Resources