Debugging my application, there is an object (only one) of this class:
public class MqttInterface implements MqttPlatformInterfaceObserver{
private MqttMessage lastMessage;
....
public MqttMessage getLastMessage() {
return lastMessage;
}
#Override
public void mqttMessageArrived(String message) {
try {
lastMessage = new JSONParser().parseJsonBodyAs(MqttMessage.class, message);
}
catch (IOException e) {
e.printStackTrace();
}
}
}
The void mqttMessageArrived(String) method is implemented using an Observer design pattern, so the object is registered and notified when a new message arrives.
I have two breakpoints (one in each method body) At some point after some time application is running, I get that when getLasMessage() message is passed to the object, it is returning a old lastMessage object with old state. Although mqttMessageArrived(String) is being called later several times the lastMessage object returned by getLastMessage() method keep being the same and it is never updated .
I check that the lastMessage attribute is being updated by mqttMessageArrived method (no Exception is thrown) and indeed when the program stops in the mqttMessageArrived method because the breakpoint, I see lastMessage state is being updated, but after that when the program stops in getLastMessage method(), it has the same old state.
I dont understand how this behaviour is possible for the same object, I have been thinking it is related with some concurrency or some cache issue.
Related
So I'm using ListenableFuture as a return type for certain operations. I expect the users to add callback to the future and then handle the success and exception cases. Now if the user cannot handle the exception, I want to have the ability to throw that exception onto the main Thread. Here's some code example:
public class SomeProcessor {
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
public ListenableFuture<String> doStringProcessing() {
return executor.submit(() -> doWork());
}
private String doWork() {
return "stuff";
}
}
Then in a client class:
public class SomeConsumer {
public SomeConsumer (SomeProcessor processor) {
Futures.addCallback(processor.doStringProcessing(), new FutureCallback<String>() {
#Override
public void onSuccess(String result) {
// do something with result
}
#Override
public void onFailure(Throwable t) {
if (t instanceof ExceptionICanHandle) {
// great, deal with it
} else {
// HERE I want to throw on the Main thread, not on the executor's thread
// Assume somehow I can get a hold of the main thread object
mainThread.getUncaughtExceptionHandler().uncaughtException(mainThread, t);
// This above code seems wrong???
throw new RuntimeException("Won't work as this is not on the mainthread");
}
}
}, MoreExecutors.directionExecutor());
}
}
There is no direct way to do this.1
Hence, this question boils down to a combination of 2 simple things:
How do I communicate some data from a submitted task back to the code that is managing the pool itself? Which boils down to: How do I send data from one thread to another, and...
How do I throw an exception - which is trivial - throw x;.
In other words, you make the exception in your task, and do not throw it, instead, you store the object in a place the main thread can see it, and notify the main thread they need to go fetch it and throw it. Your main thread waits for this notification and upon receiving it, fetches it, and throws it.
A submitted task cannot simply 'ask' for its pool or the thread that manages it. However, that is easy enough to solve: Simply pass either the 'main thread' itself, or more likely some third object that serves as common communication line between them, to the task itself, so that task knows where to go.
Here is one simplistic approach based on the raw synchronization primitives baked into java itself:
public static void main(String[] args) {
// I am the main thread
// Fire up the executorservice here and submit tasks to it.
// then ordinarily you would let this thread end or sleep.
// instead...
ExecutorService service = ...;
AtomicReference<Throwable> err = new AtomicReference<>();
Runnable task = () -> doWork(err);
service.submit(task);
while (true) {
synchronized (err) {
Throwable t = err.get();
if (t != null) throw t;
err.wait();
}
}
}
public void doWork(AtomicReference<Throwable> envelope) {
try {
doActualWork();
catch (Throwable t) {
synchronized (envelope) {
envelope.set(t);
envelope.notifyAll();
}
}
}
There are many, many ways to send messages from one thread to another and the above is a rather finicky, primitive form. It'll do fine if you don't currently have any comms channels already available to you. But, if you already have e.g. a message queue service or the like you should probably use that instead here.
[1] Thread.stop(someThrowable) literally does this as per its own documentation. However, it doesn't work - it's not just deprecated, it has been axed entirely; calling it throws an UnsupportedOperationException on modern VMs (I think at this point 10 years worth of releases at least), and is marked deprecated with the rather ominous warning of This method is inherently unsafe. and a lot more to boot, it's not the right answer.
I have a FileCreator class that implements StreamResourceWriter interface and MainErrorHandler class that implements ErrorHandler. I'm using the MainErrorHandler class as a centralized Exception handler in my project which mostly logs the exception and shows a notification to the user. The problem is that StreamResourceWriter.accept() method runs in a non UI thread and when an Exception is thrown it is directed to the ErrorHandler which then fails to show a notification due to "IllegalStateException: UI instance is not available". Is there a way to show a notification window to the user from MainErrorHandler when FileCreator throws an error in accept() method?
Below FileCreator snippet.
public class FileCreator implements StreamResourceWriter {
#Override
public void accept(OutputStream stream, VaadinSession session) throws IOException {
// Run in a non ui thread.
// Writes to OutputStream but an Exception might be thrown during this process
}
}
Below MainErrorHandler snippet.
/**
* Centralized error handler
*/
public class MainErrorHandler implements ErrorHandler {
private static final Logger log = LoggerFactory.getLogger(MainErrorHandler.class);
#Override
public void error(ErrorEvent event) {
log.error("Error occurred", event.getThrowable());
//Cannot show a notification if ErrorEvent came from FileCreator.
//Will get an IllegalStateException: UI instance is not available.
Notification.show("Error occurred");
//Tried UI.getCurrent but it returns null if ErrorEvent came from FileCreator.
UI.getCurrent();
}
}
Using Vaadin 13.0.1.
Edit
One way to solve this issue is to pass UI reference to FileCreator directly. Below an example.
public class FileCreator implements StreamResourceWriter {
private UI ui;
//Pass UI reference directly
public FileCreator(UI ui){
this.ui = ui;
}
#Override
public void accept(OutputStream stream, VaadinSession session) throws IOException {
try{
// Run in a non ui thread.
// Writes to OutputStream but an Exception might be thrown during this process
}catch(Exception e){
//I don't like this since have to catch all exceptions and have to call ErrorHandeler directly with a UI reference. Also what if somewhere in code ErrorHandler is changed and is not of type MainErrorHandler.
((MainErrorHandler)VaadinSession.getCurrent().getErrorHandler()).error(e, ui);
}
}
}
As I said in comments I really don't like this approach either since I am forced to catch all Exceptions, have to cast ErrorHandler to MainErrorHandler and calling it directly.
There is a way, but it's not perfect.
You can get all UI instances via VaadinSession.getCurrent().getUIs().
To filter out the inactive/detached UIs you can check if ui.getSession() returns a VaadinSession (so, not null). The JavaDoc of getSession says:
The method will return null if the UI is not currently attached to a VaadinSession.
Then you can invoke the access method on each of the UIs and create and show the notification inside the UI-context.
for(UI ui : VaadinSession.getCurrent().getUIs()) {
// Filtering out detached/inactive UIs
if (ui.getSession() != null) {
ui.access(() -> {
// create Notification here
});
}
I said it's not perfect because you have to keep in mind that the user can have several UIs opened at the same time(e.g. multiple tabs).
While using Unirest, the program doesn't exit until we manually shutdown every thread by invoking Unirest.shutdown(). If I had to make just one request, it's easy:
private static void asyncRequest (String link) {
try {
Future <HttpResponse <JsonNode>> request = Unirest.head(link).asJsonAsync(
new Callback<JsonNode>() {
#Override
public void completed(HttpResponse<JsonNode> httpResponse) {
print(httpResponse.getHeaders());
try {
Unirest.shutdown();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void failed(UnirestException e) {
print(e.getMessage());
}
#Override
public void cancelled() {
print("Request cancelled");
}
}
);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
asyncRequest("https://entrepreneur.com");
}
But I have to make multiple HTTP request in parallel (subsequent requests are meant not to wait for previous requests to complete). In the code above, I have to execute the code inside asyncRequest more than once with different links. The problem is I can't decide when to invoke Unirest.shutdown() so that the program exits as soon as the last request receives response. If I call Unirest.shutdown() after all the calls to asyncRequest in main, some or all the requests might get interrupted. If I call it inside completed (and other overridden methods), only the first request is made and others are interrupted. How can I solve this?
In theory, you could make the current thread wait for the execution of the method and after they are all done you can call the shutdown. But this would make the whole process synchronous, which is not what we want. So what I would do is, run different thread (other than the main one) which will wait for the execution of all your http requests. To do so you can use the class CountDownLatch, initializing with the countdown before it releases the control to the parent thread. You pass the instance of the CountDownLatch to the async method and you decrease by one each time you complete an http request. When it reaches 0 it returns the control to the parent thread, where you know you can call shutdown method as all your requests are done.
In my java application, I have a string (MySingleton.getInstance().myString) which gets updated based on user actions. In this application, there is a TCP server which sends the value of this string to all connected clients whenever the value of the string changes.
Each client socket gets its own thread. Here is the thread code.
public void run() {
try {
PrintStream printStream = new PrintStream(hostThreadSocket.getOutputStream(), true);
while (true) {
synchronized (MySingleton.getInstance()) {
printStream.println(MySingleton.getInstance().myString);
try {
MySingleton.getInstance().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
And here is the code which writes to MySingleton.getInstance().myString.
public void updateString(String newString) {
synchronized (MySingleton.getInstance()) {
MySingleton.getInstance().myString = newString;
MySingleton.getInstance().notifyAll();
}
}
I am not familiar with synchronization in java so I am not much confident about my code. Can anybody notice anything wrong?
It should be fine, provided that MySingleton.getInstance() always returns the same object.
If the method call returns different objects at different points in time, then you may get exceptions due to synchronizing on one instance, and then calling wait or notify on a different instance. In addition, there may be memory hazards because you are not synchronizing on the object that you are accessing / updating.
So this is in reference to my previous questions here and here. Basically the problem I am having is the program goes into the Server class and stays there because there is a while look in the server code that essentially is continuously listening to the port for any response from the client; this makes the Main window completely unclickable since the program is not in the MainWindow class.
But really what I want it to do is setup the connection and then go back to MainWindow so the on-screen buttons are clickable. Or, as suggested by one poster, I could pass the MainWindow object by reference to the Server (which I have already done) and then use SwingUtilities.invokeLater() but I'm not really looking to update the GUI. I'm looking to give control back to the GUI so the user can click buttons and such.
When it goes back to MainWindow, I still need the connection to stay alive so the client can send things and I can receive it and display the received content on the screen for the user to control.
Basically, you could use a SwingWorker to perform actions in the background, off the Event Dispatching Thread, which will allow you application to continue working...
SwingWorker<Server , Object> worker = new SwingWorker<Server , Object>() {
#Override
protected ServerdoInBackground() throws Exception {
Server server = new Server();
//...
// Use publish(...) to send information
// back the EDT via the process method...
return server;
}
#Override
protected void done() {
try {
Server server = get();
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
}
#Override
protected void process(List<Object> chunks) {
// You can safly update the UI from here, maybe
// with some messages??
}
};
worker.execute();
Basically, this creates a new Server object in the doInBackground method, does what ever else it needs to do that might otherwise block the EDT and exits by returning the server instance.
You can use done if you want to be notified when the doInBackground method completes and either get the result of the method, or if it threw an exception, handle the exeption.
The publish/process methods can be used to send information back to the EDT, which could be used to update the state of the UI...or not...
Now, if you already have a reference to the server, may consider creating a custom SwingWorker to which you pass the reference of the Server to...
Server server = ...;
ConnectionWorker worker = new ConnectionWorker(server);
worker.execute();
//...
public class ConnectionWorker extends SwingWorker<Object, Object> {
private Server server;
public ConnectionWorker(Server server) {
this.server;
}
#Override
protected ServerdoInBackground() throws Exception {
server.doStuff(); //...
return ...;
}
}
Take a look at SwingWorker more details