Submit Callable with ExecutorService in static block - executorservice

I encountered a strange problem while using ExecutorService to execute a Callable in static block. let's see the complete code directly as below.
package com.acme;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class App {
private static int data = 0;
static {
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<String> future = executor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
System.out.println("" + data);
return "hello";
}
});
}
public static void main(String[] args) {
System.out.println("enter main scope");
}
}
Run the main method, the result is presented as below screenshot.
enter image description here
However, if I add some business code as below, nothing is printed in the console.
public class App {
private static int data = 0;
static {
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<String> future = executor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
System.out.println("" + data);
return "hello";
}
});
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("enter main scope");
}
}
Anyone can provide some help about this issue? more details are preciated.

As you made executor code run in static block which force the code to run even before App.class context is full created (i.e class not fully loaded in memory or you can say now "data" variable is not in memory ).
Basically when your call method get called through executor its(thread) trying to find the variable "data" in App.class but it might not be loaded till now, this is also making thread run infinite.
Solution :
Run the executor in main block but still there is a issue ,suppose if for some reason (business logic) the App.class get unloaded you will be again stuck with a infinitely running thread that is finding "data".
Make the data variable "final", then you can put your code either is static block or static method (Ex. main). As for final variable a separate copy is maintained and has issue of class loading or unloading above issue will not come.

Related

Flutter Platform Channels - Invoke channel method on android, hangs the ui

I'm trying to use Tesseract in flutter using the following package https://github.com/arrrrny/tesseract_ocr
I've download the app and run in.
The problem is that the extractText hangs the UI.
Looking at the Java code:
Thread t = new Thread(new Runnable() {
public void run() {
baseApi.setImage(tempFile);
recognizedText[0] = baseApi.getUTF8Text();
baseApi.end();
}
});
t.start();
try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); }
result.success(recognizedText[0]);
I can see that it is running on a new thread, so I expect it not to hang the app, but it still does.
I found this example:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// Call the desired channel message here.
baseApi.setImage(tempFile);
recognizedText[0] = baseApi.getHOCRText(0);
baseApi.end();
result.success(recognizedText[0]);
}
});
from https://flutter.dev/docs/development/platform-integration/platform-channels#channels-and-platform-threading
but it also hangs the UI.
The docs also say
**Channels and Platform Threading**
Invoke all channel methods on the platform’s main thread when writing code on the platform side.
Can someone clarify this sentence?
According to Richard Heap answer, I tried to call a method from native to dart, passing the result:
Dart side:
_channel.setMethodCallHandler((call) {
print(call);
switch (call.method) {
case "extractTextResult":
final String result = call.arguments;
print(result);
}
var t;
return t;
});
Java side:
channel.invokeMethod("extractTextResult","hello");
if I call this method from the main thread, this works fine, but then the thread is blocking.
If I do
Thread t = new Thread(new Runnable() {
public void run() {
channel.invokeMethod("extractTextResult","test1231231");
}
});
t.start();
result.success("tst"); // return immediately
Then the app crashes with the following message:
I also tried:
Thread t = new Thread(new Runnable() {
public void run() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// Call the desired channel message here.
baseApi.setImage(tempFile);
recognizedText[0] = baseApi.getHOCRText(0);
baseApi.end();
result.success(recognizedText[0]);
// channel.invokeMethod("extractTextResult", "test1231231");
}
});
}
});
t.start();
result.success("tst");
which is what I understand that Richard Heap last comment meant, but It still hangs the ui.
I had the same Issue and fixed it with a MethodCallWrapper in TesseractOcrPlugin.java
This Code works for me (no Dart-code change is needed):
package io.paratoner.tesseract_ocr;
import com.googlecode.tesseract.android.TessBaseAPI;
import android.os.Handler;
import android.os.Looper;
import android.os.AsyncTask;
import java.io.File;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
/** TesseractOcrPlugin */
public class TesseractOcrPlugin implements MethodCallHandler {
private static final int DEFAULT_PAGE_SEG_MODE = TessBaseAPI.PageSegMode.PSM_SINGLE_BLOCK;
/** Plugin registration. */
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "tesseract_ocr");
channel.setMethodCallHandler(new TesseractOcrPlugin());
}
// MethodChannel.Result wrapper that responds on the platform thread.
private static class MethodResultWrapper implements Result {
private Result methodResult;
private Handler handler;
MethodResultWrapper(Result result) {
methodResult = result;
handler = new Handler(Looper.getMainLooper());
}
#Override
public void success(final Object result) {
handler.post(new Runnable() {
#Override
public void run() {
methodResult.success(result);
}
});
}
#Override
public void error(final String errorCode, final String errorMessage, final Object errorDetails) {
handler.post(new Runnable() {
#Override
public void run() {
methodResult.error(errorCode, errorMessage, errorDetails);
}
});
}
#Override
public void notImplemented() {
handler.post(new Runnable() {
#Override
public void run() {
methodResult.notImplemented();
}
});
}
}
#Override
public void onMethodCall(MethodCall call, Result rawResult) {
Result result = new MethodResultWrapper(rawResult);
if (call.method.equals("extractText")) {
final String tessDataPath = call.argument("tessData");
final String imagePath = call.argument("imagePath");
String DEFAULT_LANGUAGE = "eng";
if (call.argument("language") != null) {
DEFAULT_LANGUAGE = call.argument("language");
}
calculateResult(tessDataPath, imagePath, DEFAULT_LANGUAGE, result);
} else {
result.notImplemented();
}
}
private void calculateResult(final String tessDataPath, final String imagePath, final String language,
final Result result) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
final String[] recognizedText = new String[1];
final TessBaseAPI baseApi = new TessBaseAPI();
baseApi.init(tessDataPath, language);
final File tempFile = new File(imagePath);
baseApi.setPageSegMode(DEFAULT_PAGE_SEG_MODE);
baseApi.setImage(tempFile);
recognizedText[0] = baseApi.getUTF8Text();
baseApi.end();
result.success(recognizedText[0]);
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}.execute();
}
}
By using join you're making the main thread wait for the background thread, blocking it. You have to remove the join and return a result immediately.
So, how do you return the ocr result, which won't be available immediately. When it becomes available, you then call a method from native to dart, passing the result. At the dart end, you then handle the result as any async event.
The point of the last paragraph of your question is that your result will become available on your background thread, so you'd want to call the native to dart method there. You can't. You have to post the method call code to the main looper - you already show some code for posting to the main looper which you can use as an example.
Based on Richard Heap answer I came up with this:
Dart code:
_channel.setMethodCallHandler((call) {
switch (call.method) {
case "extractTextResult":
final String result = call.arguments;
print(result);
}
var t;
return t;
});
Java code:
Thread t = new Thread(new Runnable() {
public void run() {
baseApi.setImage(tempFile);
recognizedText[0] = baseApi.getHOCRText(0);
baseApi.end();
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
channel.invokeMethod("extractTextResult", recognizedText[0]);
}
});
}
});
t.start();
result.success("tst");
explain:
This code will run the Java extractText in a separate thread, and when the result is ready it will hopp back to the ui thread with the call to Looper.getMainLooper() which will then send the message back to the Dart side which must receive the message on the ui thread, which is what this message means:
**Channels and Platform Threading**
Invoke all channel methods on the platform’s main thread when writing code on the platform side.
NOTE on the Dart side, this is still incomplete example since you then need to report to the ui that a message received, this can be done with a Completer, which is used to create and complete a future
At the end of your method channel just return the response back to dart side
Add this line at the end of method channel result.success(true)
full example
override fun configureFlutterEngine(#NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
"method-channel"
).setMethodCallHandler { call, result ->
if (call.method == "getFirebaseAppCheckDebugToken") {
...
result.success(true) // just add this line
}
}
}```

Cucumber run time exception

this question is the duplicate post. the reason i ask is I couldn't get a valid answer (or at least the answer that i could understand) from them
hence I am asking again.
below is the code.there is an executable RunnerTest and a baseClass
#RunWith(Cucumber.class)
#CucumberOptions(plugin = {"html:target/whisper-html-report", "json:target/whisper_report.json", "com.cucumber.listener.ExtentCucumberFormatter:output/report.html"},tags = {"#Tag"})
public class RunnerTest {
}
public class BaseClass {
#Before
public void startUp() {
try {
driver = webModel.getUtils().browser();
driver.get(webModel.getUtils().getProperty("url"));
driver.manage().window().maximize();
} catch (Exception e) {
e.printStackTrace();
}
}
#After
public void tearDown(Scenario scenario) throws IOException {
if (scenario.isFailed()) {
TakesScreenshot camera = (TakesScreenshot) driver;
byte[] screenshot = camera.getScreenshotAs(BYTES);
scenario.embed(screenshot, "image/png");
System.out.println("screenShot taken");
}
driver.close();
driver.quit();
}
}
Feature file
#Tag
Feature: will this run
Scenario: try to execute feature
Given I feel like running the code
Then I run the code
Step definition-
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
public class run_this_MyStepdefs {
#Given("^I feel like running the code$")
public void iFeelLikeRunningTheCode() {
System.out.println("yes i feel like running the code");
}
#Then("^I run the code$")
public void iRunTheCode()
{
System.out.println("hence i am running the code");
}
}
below us the error code
cucumber.runtime.CucumberException: Failed to instantiate classBaseClass
I was trying to instantiate the base class, and this was the reason for the cucumber exceptions.
The moment I removed the base class object, all seemed to work fine.

Service class does not run

I have the following section of JavaFX that implements Service class:
public void processingImage() {
Task<Void> track = new Task<Void>() {
#Override
protected Void call() throws Exception {
while (true) {
if (flag == false) {
if (someCondition) {
flag = true;
CommunicateServer.sendObject = new Object[2];
CommunicateServer.sendObject[0] = 6;
CommunicateServer.sendObject[1] = "hello";
myService.start();
flag = false;
System.out.println("this line does not print");
}
}
return null;
}
};
Thread th1 = new Thread(track);
th1.setDaemon(true);
th1.start();
}
And the MyService class is implemented as:
private class MyService extends Service<Void> {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
CommunicateServer.callSendObject(CommunicateServer.sendObject, true);
response = CommunicateServer.getObject();
System.out.println("this print should have been many times but only executed once!!!!");
return null;
}
};
}
}
My problem is although I expect the code to print this line does not print, the code actually does not print this. Moreover, the line this print should have been many times but only executed once!!!! is printed only once although I think it should have been printed many times. I don't know how to fix this problem. Any help or suggestion will be met with gratitude.
It's not really clear what you expect your code to do, but Service.start() should be called from the FX Application Thread. Since you are calling it from a background thread, this may be throwing an exception, preventing you reaching the System.out.println(...) statement.
Moreover, the service must be in the READY state to receive the call to start(), so on the second execution (if there is one), since the service has not been reset, you will get an IllegalArgumentException, exiting the call() method in the task defined in processingImage(). Hence your service will execute at most once.

Is it possible to write a custom redirect in java

I am testing an application.
My test is complex, and I spawn 2 thread that start 2 process builders which spawn 2 java processes.
Is it possible to write a custom redirect that will be similar to inherit but prepend something to every out and err message, so that I would know its origin.
Example code below:
public class test {
public static void main(String... args){
Thread t = new Thread(new testHelper());
t.start();
t = new Thread(new testHelper());
t.start();
}
}
import java.io.IOException;
public class testHelper implements Runnable {
#Override
public void run() {
Class klass = testWorker.class;
System.out.println(klass.getCanonicalName());
String separator = System.getProperty("file.separator");
String classpath = System.getProperty("java.class.path");
String path = System.getProperty("java.home")
+ separator + "bin" + separator + "java";
ProcessBuilder processBuilder =
new ProcessBuilder(path, "-cp",
classpath,
klass.getCanonicalName());
processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
processBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process process = null;
try {
process = processBuilder.start();
} catch (IOException e) {
e.printStackTrace();
}
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Child Process is done");
}
}
public class testWorker {
public static void main(String ... args) throws InterruptedException {
System.out.println("Doing some stuff");
Thread.sleep(10000);
System.out.println("Finished doing some stuff");
}
}
No, its not possible. In the source code for java.lang.ProcessBuilder.Redirect the constructor is private and has this to say
/**
* No public constructors. Clients must use predefined
* static {#code Redirect} instances or factory methods.
*/
private Redirect() {}

How to execute my RETURN on my method until THREAD is procesed?

I have a method in my class that returns a STRING procesed on a thread and I need to wait to resolve the work on my thread until the RETURN is executed. Any idea to resolve it ?? Can I have a simple example for this ??
Thanks.
If java then Callable interface was done exactly for this:
class CalculateSomeString implements Callable<String>{
#Override
public String call() throws Exception {
//Simulate some work that it takes to calculate the String
Thread.sleep(1000);
return "CoolString";
}
}
And the code that runs it
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService service = Executors.newFixedThreadPool(1);
Future<String> future = service.submit(new CalculateSomeString());
//this will block until the String has been computed
String result = future.get();
service.shutdown();
System.out.println(result);
}

Resources