so, here is my today problem:
First of all, please note that I do NOT have the Matlab parallel toolbox available.
I am running java code witch interact with Matlab. Sometime Matlab directly call some java functions, sometimes it is the opposite. In this case, we use a notification system which comes from here:
http://undocumentedmatlab.com/blog/matlab-callbacks-for-java-events
We then address the notification in proper callbacks.
Here is a simple use case:
My user select a configuration file using the java interface, loaded into Matlab.
Using an interface listener, we notify Matlab that the configuration file has been selected, it then run a certain number of functions that will analyzes the file
Once the analysis is done, it is pushed into the java runtime, which will populate interface tables with the result. This step involve that matlab will call a java function.
Finally, java request the interface to be switched to an arbitrary decided tab.
This is the order of which things would happen in an ideal world, however, here is the code of the listener actionPerformed method:
#Override
public void actionPerformed(ActionEvent arg0) {
Model wModel = controller.getModel();
Window wWindow = controller.getWindow();
MatlabStructure wStructure = new MatlabStructure();
if(null != wModel) {
wModel.readMatlabData(wStructure);
wModel.notifyMatlab(wStructure, MatlabAction.UpdateCircuit);
}
if(null != wWindow) {
wWindow.getTabContainer().setSelectedComponent(wWindow.getInfosPannel());
}
}
What happen here, is that, when the notifyMatlab method is called, the code does not wait for it to be completed before it continues. So what happen is that the method complete and switch to an empty interface page (setSelectedComponent), and then the component is filled with values.
What I would like to, is for java to wait that my notifyMatlab returns a "I have completed !!" signal, and then pursue. Which involves asynchrounous code since Matlab will code java methods during its execution too ...
So far here is what I tried:
In the MatlabEventObject class, I added an isAcknowledge member, so now the class (which I originaly found in the above link), look like this (I removed all unchanged code from the original class):
public class MatlabEventObject extends java.util.EventObject {
private static final long serialVersionUID = 1L;
private boolean isAcknowledged = false;
public void onNotificationReceived() {
if (source instanceof MatlabEvent) {
System.out.println("Catched a MatlabEvent Pokemon !");
MatlabEvent wSource = (MatlabEvent) source;
wSource.onNotificationReceived();
}
}
public boolean isAcknowledged() {
return isAcknowledged;
}
public void acknowledge() {
isAcknowledged = true;
}
}
In the MatlabEvent class, I have added a future task which goal is to wait for acknowledgement, the methods now look like this:
public class MatlabEvent {
private Vector<IMatlabListener> data = new Vector<IMatlabListener>();
private Vector<MatlabEventObject> matlabEvents = new Vector<MatlabEventObject>();
public void notifyMatlab(final Object obj, final MatlabAction action) {
final Vector<IMatlabListener> dataCopy;
matlabEvents.clear();
synchronized (this) {
dataCopy = new Vector<IMatlabListener>(data);
}
for (int i = 0; i < dataCopy.size(); i++) {
matlabEvents.add(new MatlabEventObject(this, obj, action));
((IMatlabListener) dataCopy.elementAt(i)).testEvent(matlabEvents.get(i));
}
}
public void onNotificationReceived() {
ExecutorService service = Executors.newSingleThreadExecutor();
long timeout = 15;
System.out.println("Executing runnable.");
Runnable r = new Runnable() {
#Override
public void run() {
waitForAcknowledgement(matlabEvents);
}
};
try {
Future<?> task = service.submit(r);
task.get(timeout, TimeUnit.SECONDS);
System.out.println("Notification acknowledged.");
} catch (Exception e) {
e.printStackTrace();
}
}
private void waitForAcknowledgement(final Vector<MatlabEventObject> matlabEvents) {
boolean allEventsAcknowledged = false;
while(!allEventsAcknowledged) {
allEventsAcknowledged = true;
for(MatlabEventObject eventObject : matlabEvents) {
if(!eventObject.isAcknowledged()) {
allEventsAcknowledged = false;
}
break;
}
}
}
}
What happen is that I discover that Matlab actually WAIT for the java code to be completed. So my waitForAcknowledgement method always wait until it timeouts.
In addition, I must say that I have very little knowledge in parallel computing, but I think our java is single thread, so having java waiting for matlab code to complete while matlab is issuing calls to java functions may be an issue. But I can't be sure : ]
If you have any idea on how to solve this issue in a robust way, it will be much much appreciated.
Related
So I just started playing around with JDA API trying to create a little /info command which looked like shown below.
Issue: Unfortunately the bot does not react when I type /info.
While I was debugging, I found out, that the Info command never get's called and I will explain why later, after showing you the 3 classes that are involved in this problem.
public class InfoCommand extends Command {
public InfoCommand(String name) {
super(name);
}
#Override
public void handle(MessageReceivedEvent event, String... params) {
EmbedBuilder builder = new EmbedBuilder();
builder.setTitle("Test Title");
builder.setDescription("Test Description" );
builder.setFooter("Created by t0gepi");
builder.setColor(0xf45642);
event.getChannel().sendTyping().queue();
event.getChannel().sendMessageEmbeds(builder.build()).queue();
}
}
It has a method handle which will be called by a CommandManager, whenever /info is typed in the discord server.
So far so good.
Now the Main method is also quite simple. It just starts the bot and adds the CommandManager as a Listener to JDA:
public class Main {
public static JDA jda;
public static void main(String[] args) throws LoginException {
ResourceManager.init();
jda = JDABuilder.createDefault(ResourceManager.getProperty("discord.bottoken")).build();
jda.getPresence().setStatus(OnlineStatus.IDLE);
jda.getPresence().setActivity(Activity.playing("Sleeping"));
try {
jda.awaitReady();
} catch (InterruptedException e) {
e.printStackTrace();
}
CommandManager commandManager = new CommandManager();
commandManager.addCommand(new InfoCommand("info"));
jda.addEventListener(new CommandManager());
}
}
Lastly, let's get to the CommandManager:
public class CommandManager extends ListenerAdapter {
private Set<Command> commands;
public CommandManager(){
this.commands = new HashSet<>();
}
public void addCommand(Command command){
commands.add(command);
}
#Override
public void onMessageReceived(#NotNull MessageReceivedEvent event) {
String[] msg = event.getMessage().getContentRaw().split(" ");
String prefix = ResourceManager.getProperty("command.prefix");
String[] params = null;
if(!msg[0].startsWith(prefix)){
return;
}
if(msg.length > 1){
params = Arrays.copyOfRange(msg,1,msg.length);
}
Iterator<Command> iterator = commands.iterator();
Command command;
while(iterator.hasNext()){
command = iterator.next();
if(command.getAliases().stream().anyMatch(alias -> msg[0].equalsIgnoreCase(prefix + alias))){
command.handle(event, params);
return;
}
}
// Do nothing here if command wasn't found.
}
}
Now let's get to the actual issue, why does the InfoCommands handle method not get called? Keep in mind that
InfoCommand has bin initialized and added to the CommandManager
The CommandManagers onMessageReceived method is in fact being called when a message is typed
As I was debugging, I found out why but could not find an explanation to it.
The reason why the handle method of InfoCommand does not get called, is because as to the time when onMessageReceived gets called, the CommandManagers set of commands is empty.
Why is that? I added the InfoCommand in the beginning right?
When I added the InfoCommand in the beginning, the set of commands had a size of 1. All good. But when onMessageReceived got called, the set of Commands suddenly had a size of 0, which means that the Iterator doesn't have anything to iterate over.
Why is that? I furthermore found out the following:
As to the time where I initialized the CommandManager, the CommandManager had a different memory adress than when it's onMessageReceived method got called.
So somehow, JDA must have created another new instance of CommandManager and used that, instead of my instance, right?
I hope someone understands this and let me know if you have any questions :)
Thanks for reading that far and if you'd like, you can take a better look at all the files in this Project here. There really aren't much more.
You are creating a new instance of your command manager when you register it:
jda.addEventListener(new CommandManager());
Instead, you should just pass in the instance you previously created:
CommandManager commandManager = new CommandManager();
commandManager.addCommand(new InfoCommand("info"));
jda.addEventListener(commandManager);
So I'm completely lost on this one, it might be obvious solution or I'm just trying somethin that's not possible but here it is.
I have two classes one is being used as e listener class and second one is the one that handles queue(i will only include relevant code).
Handler class:
public void check() {
for (Queueable queueable : queue) {
if (!doesReceiverHavePlayers(queueable)) continue;
}
}
private boolean doesReceiverHavePlayers(Queueable queueable) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("PlayerCount");
out.writeUTF(queueable.getReceiver());
Player player = Iterables.getFirst(Bukkit.getOnlinePlayers(), null);
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
return /*response*/ > 0;
}
Listener class:
#Override
public void onPluginMessageReceived(String channel, #NotNull Player player, byte[] message) {
if (!channel.equals("BungeeCord")) return;
ByteArrayDataInput in = ByteStreams.newDataInput(message);
String subChannel = in.readUTF();
switch (subChannel) {
case "PlayerCount":
int response = in.readInt();
break;
}
}
The check method is called every 5 seconds and doesReceiverHavePlayers requests player count from a certain server to see if there are any players on it, but the 'response' arrives in the listener class onPluginMessageReceived method. But as you can see I'm trying to use response in the doesReceiverHavePlayers method and return boolean value. Is there any way I can achieve this and how should I do it?
In onPluginMessageReceived store the result in a ConcurrentHashMap and then lookup the value in doesReceiverHavePlayers instead of making a blocking call.
Something like this:
ConcurrentHashMap<String, Integer> playerCounts = new ConcurrentHashMap<>();
void onPluginMessageReceived() {
playerCounts.put(subChannel, response);
}
boolean doesReceiverHavePlayers() {
return playerCounts.get(queueable.getReceiver()) > 0;
}
I am using ActivityScenarioRule for Espresso UI Testing and I wanted to get access to the method getStringArray(), calling which requires the Activity . So, is there any way to retrieve the Activity by the ActivityScenarioRule , maybe something similar to getActivity in ActivityTestRule.
#Rule
public ActivityScenarioRule activityScenarioRule = new ActivityScenarioRule<>(MainActivity.class);
I am not using ActivityTestRule, because it is deprecated!
Since it appears you're using Java, here's how you'd do it:
#Rule
ActivityScenarioRule<MainActivity> activityScenarioRule = new ActivityScenarioRule<>(MainActivity.class);
#Test
public void test() {
activityScenarioRule.getScenario().onActivity(activity -> {
// use 'activity'.
});
}
Please read the documentation for more info on these new ways of interacting with the activity under test.
For anyone who wants Activity, but that without need to re-write all tests to run on UI-thread, a fairly straightforward Java way to get it:
Waiting for UI
Assume you want to test if a dialog is shown after some delay, the onActivity(...) hook runs on UI-thread, which means waiting in there would cause the dialog to be nerver shown.
In such cases you need to keep a strong-reference to ActivityScenario (as that prevents Activity close).
Test should wait for onActivity(...) hook to be called, then keep passed Activity's reference.
Finally, move test logic out of onActivity(...) hook.
Example
private ActivityScenario mActivityScenario;
#After
public void tearDown() throws Exception {
if (mActivityScenario != null) {
mActivityScenario.close();
}
mActivityScenario = null;
}
#Override
public Activity getActivity() {
if (mActivityScenario == null) {
mActivityScenario = ActivityScenario.launch(getActivityClassForScenario());
}
return tryAcquireScenarioActivity(mActivityScenario);
}
protected static Activity tryAcquireScenarioActivity(ActivityScenario activityScenario) {
Semaphore activityResource = new Semaphore(0);
Activity[] scenarioActivity = new Activity[1];
activityScenario.onActivity(activity -> {
scenarioActivity[0] = activity;
activityResource.release();
});
try {
activityResource.tryAcquire(15000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Assert.fail("Failed to acquire activity scenario semaphore");
}
Assert.assertNotNull("Scenario Activity should be non-null", scenarioActivity[0]);
return scenarioActivity[0];
}
Espresso states the following:
At the same time, the framework prevents direct access to activities
and views of the application because holding on to these objects and
operating on them off the UI thread is a major source of test
flakiness.
When there is no other way I use the following method to get an arbitrary activity from an ActivityScenarioRule. It uses onActivity mentioned in the accepted answer:
private <T extends Activity> T getActivity(ActivityScenarioRule<T> activityScenarioRule) {
AtomicReference<T> activityRef = new AtomicReference<>();
activityScenarioRule.getScenario().onActivity(activityRef::set);
return activityRef.get();
}
Any onView(...) code inside onActivity led to a timeout in my testcases. So, I extracted the activity and used it with success outside the onActivity. Beware tho! See the statement above.
#Test
fun checkForUpdate() {
val scenario = ActivityScenario.launch(MainActivity::class.java)
scenario.onActivity {
UpdateTool.checkForUpdate(it)
}
}
I'm using a recursive method which implements the use of the SwingWorker class to do a research in one folder and all its subfolders - in the local hard drive.
Basically works fine but I'm stuck when I want to stop the SwingWorker method: when the user change the 'source folder' (I'm using a JTree - JAVAFX - to show all the folders in the local hard drive), I want to stop the current 'SwingWorker research' in that folder and start a new one, with the newest 'source path' results choosed from the user.
All the results of the research are stored in a private ObservableList - and updated everytime in the done() method, just by filling one TableView - JavaFX: so, when the user change the 'source path' I have to clean the results of the previous research.
Start method:
private static ObservableList<msg> data = FXCollections.observableArrayList();
private static SwingWorker<Void, Void> worker;
private static String currentFolder;
#Override
public void start(Stage primaryStage) throws Exception {
// TODO Auto-generated method stub
stage = primaryStage;
primaryStage.setScene(new Scene(createContent()));
styleControls();
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setMaximized(true);
primaryStage.setFullScreen(false);
primaryStage.show();
msgp = new MsgParser();
}
createContent() method- recursive function its called here:
public Parent createContent() {
tree.getSelectionModel().selectedItemProperty().addListener( new ChangeListener<Object>() {
#Override
public void changed(ObservableValue observable, Object oldValue,
Object newValue) {
TreeItem<File> selectedItem = (TreeItem<File>) newValue;
currentFolder = selectedItem.getValue().getAbsolutePath();
// I want to stop here the previous SwingWorker call : the tree
// ChangeListener event is called when the user change the
// source folder of the research, by selecting one TreeItem on it.
if(worker!= null)
worker.cancel(true);
//Here I clean previous results
data.clear();
TV.setItems(data);
//And I call again the method with the new source Folder
ListMail(new File(currentFolder));
}
});
}
ListMail() method: [recursive SwingWorker]
private void ListMail(File dir) {
worker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
File[] directoryListing = dir.listFiles();
if (directoryListing != null) {
for (File child : directoryListing) {
if(!worker.isCancelled()) {
if(child != null){
if(!child.isDirectory()) {
if(child.getAbsolutePath().substring(child.getAbsolutePath().lastIndexOf('.')+1).equals("msg")) {
Message message = msgp.parseMsg(child.getPath());
String percorsoMail = child.getAbsolutePath().toUpperCase();
if(message != null) {
String fromEmail = message.getFromEmail();
String fromName = message.getFromName();
String subject = message.getSubject();
String received = message.getDate().toString();
String name;
if(fromEmail != null)
name = fromName + "(" + fromEmail + ")";
else name = fromName;
msg Message = new msg(name, subject, received);
if(!data.contains(Message))
data.add(Message);
//I use the Platform.runLater to
// take count of the number of results found
//It updates the GUI - works fine
Platform.runLater(new Runnable() {
#Override public void run() {
if(data != null && data.size() > 0)
setStatusLabel(data.size());
else
setStatusLabel(0);
}
});
}
}
} else {
/**
* Recursive call here : I do the research
* for the subfolders
*/
ListMail(child);
}
} else {
}
}
}
}
return null;
}
// Update GUI Here
protected void done() {
// I refresh here the TableView: works fine on-the-fly added results
TableView.setItems(data);
TableView.refresh();
}
};
//This doesn't do anything
if(!worker.isCancelled())
worker.execute();
}
Basically, the issue is that the SwingWorker thread never stop, I'm thinking because of the recursive calls which creates new pid process at every run or something ?
Also by using a dedicated external button, which I prefer to avoid, gives no results:
refreshBtn.setOnAction(e -> {
//Handle clicks on refreshBtn button
worker.cancel(true);
});
After I click on TreeItem to change source-folder, it just delete all the ObservableList elements created at that moment, but the previous research don't stop.
Everything works fine instead if I wait the research its finished - but this can works only when I'm in a deep-level folder, while I can't obviously wait when the research start with the "C:\" folder.
Ok so that's here how I managed this by using javafx.concurrent.
Just to point my experience with this, it seems using a recursive background Task for potentially long computations, such as scanning the Whole local drive like in my example, it's very memory consuming - also because I stored some results of this background computation in static local variables to access them faster: the result was a data-structure (ObservableList) with over 5000+ instances of a custom class to represent that specific data computed and then the OutOfMemoryError message or the background thread just going like in 'stand-by' without any advice after running for long time (waiting for garbage collection?).
Anyway here's the code that sum up how I solved: the threads are correctly closed. By the way, sometimes, there's a little 'GUI delay' due to cleaning the GUI on the isCancelled() method check: the GUI swing between clear/not clear, because in my opinion it keeps get filled by the results of the previous tasks in the recursion.
private static BackgroundTask backgroundTask;
private static Thread thread;
tree.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
#Override
public void changed(final ObservableValue observable, final Object oldValue, final Object newValue) {
//I close previous running background tasks if there's any
if (backgroundTask != null) {
while (backgroundTask.isRunning()) {
backgroundTask.cancel(true);
// reset GUI nodes here used to show results of the previous thread
}
}
backgroundTask = new BackGoundTask();
thread= new Thread(backgroundTask);
thread.setDaemon(true);
thread.start();
//This will be called only when latest recursion is finished, not at every run
backgroundTask.setOnSucceeded(e -> {});
}
});
BackgroundTask class:
public static class BackgroundTask extends Task<Object> {
// .. variables used by the task here
//constructor: initialize variables at every run of the Task
public BackgroundTask() {
}
#Override
protected Object call() throws Exception {
if (!isCancelled()) {
// ... Do all background work here
Platform.runLater(new Runnable() {
#Override
public void run() {
// GUI progress can goes here
}
});
//recursion here
if(something) {
//...
} else {
call();
}
} else {
//user want to cancel task: clean GUI nodes
}
return null;
}
}
I had an issue where Text to Speech would not speak anything. I realised this was due to the fact that I was attempting to call 'Speak()' before TTS had initialised.
I need to wait until TTS has initialised, so that I can call 'Speak()' successfully. I thought doing something along the lines of this would work:
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
mTTSInitialised = true;
} else {
Log.e("TTS", "Initialisation Failed!");
}
}
...
while(!mTTSInitialised){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
But this fails to initialise at all. Is there a way to do this effectively?
The initialisation of the Text to Speech engine is asynchronous, which is why you realised you have to 'wait' for it to complete, before requesting that it processes an utterance.
Even when it eventually initialises successfully, it can be subsequently killed by the system, or it can of course fail to initialise, so you always need to be ready to handle a request to speak, where the engine isn't prepared.
Add the following helper class
public class PendingTTS {
private String pendingUtterance;
private int pendingQueueType;
public String getPendingUtterance() {
return this.pendingUtterance;
}
public void setPendingUtterance(#NonNull final String pendingUtterance) {
this.pendingUtterance = pendingUtterance;
}
public int getPendingQueueType() {
return this.pendingQueueType;
}
public void setPendingQueueType(final int pendingQueueType) {
this.pendingQueueType = pendingQueueType;
}
}
Assuming you're using an Activity, you need to declare the following variables:
private volatile PendingTTS pendingTTS;
private static final int MAX_INIT_ATTEMPTS = 4;
private volatile int initCount;
and initialise the Text to Speech object in onCreate()
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
In your onInitListener you would check if there is any pending speech:
#Override
public void onInit(final int status) {
switch (status) {
case TextToSpeech.SUCCESS:
initCount = 0;
// Set up tts stuff
tts.setOnUtteranceProgressListener(YOURprogressListener);
if (pendingTTS != null) {
// We have pending speech, process it and check the result
int speechResult = tts.speak(pendingTTS.getPendingUtterance(),pendingTTS.getPendingQueueType(),
// remaining tts variables here)
switch (speechResult){
case TextToSpeech.SUCCESS:
// Result was successful
pendingTTS = null;
break;
case TextToSpeech.ERROR:
// Speech failed
// Check if it has repeatedly failed up to the max attempts
if(initCount < MAX_INIT_ATTEMPTS){
initCount ++;
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
} else {
// Totally broken - let the user know it's not working
}
break;
}
} else {
// there was nothing to process
}
break;
case TextToSpeech.ERROR:
// Check if it has repeatedly failed up to the max attempts
if(initCount < MAX_INIT_ATTEMPTS){
initCount ++;
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
} else {
// Totally broken - let the user know it's not working
}
break;
}
I've glued the above together from my code - where the speech and initialisation methods are all separated, but I tried to give you an overview above of everything you need to handle.
Elsewhere in your code, when you make a tts.speak(//stuff here) request, you need to check the result as demonstrated above, to make sure it was successful. Again, in my code, this is separated into one single method. If it does fail, you need to set the PendingTTS parameters prior to attempting to initialise again:
pendingTTS = new PendingTTS();
pendingTTS.setPendingQueueType(// your queue type);
pendingTTS.setPendingUtterance(// your utterance);
It is is successful, make sure pendingTTS is set to null.
The overall design is that if the initialisation failed, it will attempt to initialise again, up to the maximum allowed attempts. If the speech fails, it will attempt to initialise the engine again, firstly setting the PendingTTS parameters.
Hope you managed to follow that.
Hmm..
Not a very good idea.
You can try to add the text to the TTS queue and let it do it's work. This snippet can be inside button click, etc as:
tts.speak(toSpeak, TextToSpeech.QUEUE_ADD, null);
Small tutorial that would help.