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).
Related
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.
I know I'm new to this spring stuff but I've been stuck on this all day. I don't much like asking questions but maybe I'll get an idea.
So here's my problem:
I'm trying to create a Queue for processing stuff on the back end. I did this by creating a static executorservice in a component class with helper methods to run them. it seems to work like i want, and when i wire in classes i can get into those classes, but it seems like when those are running they lose application context (or something this is just my guess).
I'm sure There are better ways to do this, but in the custom framework I am working in there are a number of features that will not work for me. I have no spring-config.xml, cannot use #Configuration
executor service component
#Component
public class FifoComponent {
public static ExecutorService executors = Executors.newSingleThreadExecutor();
private static Lock lock = new ReentrantLock(true);
public static void executeNewTestJob(int i) {
lock.lock();
OrderAllocationTestJob job = new OrderAllocationTestJob(i);
executors.execute(job);
lock.unlock();
}
}
Runnable component - note appdateutils has a method that calls a component that and works fine in my typical tomcat environment
#Component
public class OrderAllocationTestJob implements Runnable {
int i;
public OrderAllocationTestJob(int i) {
this.i = i;
}
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Asynchronous task " + i);
System.out.println(AppDateUtils.getCurrentTimeStamp());
}
}
call from a struts 2 action (test) i know I can call the appdateutils.gettime method from
for (int i = 0; i < 50; i++) {
FifoComponent.executeNewTestJob(i);
}
here's the exception i end up with for what it's worth
"Scope 'request' is not active for the current thread"
Exception in thread "pool-15-thread-50" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dateTimestampDao': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
"I'm sure There are better ways to do this"
Based on this, you'll need to create/lookup all request and session scoped components before call another thread. Actually, request injection is thread local and can't works in your scenario.
i think if u remove
Thread.sleep(100);
in OrderAllocationTestJob to
job.sleep(100);
in FifoComponent will fix your problem
I solved this solution by extending ConcurrentLinkedQueue for my runnables and keeping them in a manager I instantiated in the initialize method of a ServletContextListener. By overriding the offer() method of the ConcurrentLinkedQueue to continually poll until the queue was empty I was able synchronously process runnables.
Unfortunately this locks down the request thread until the runnable is done and I will have to have my users keep an eye on it and let me know if the pages end up running long, but at least in my test environment the process seems sub-second even when i hit it with 20 at a time so I'm OK for now.
I would still prefer an ExecutorService executed from my Tomcat container but outside the scope of the requests but unless someone can answer the question I'm just going to have to leave it for now
Are you looking something like that?
#Component
public class AsynchronousThread extends Thread {
public static final Logger LOGGER = LoggerFactory
.getLogger(AsynchronousThread.class);
#Autowired
private Writer writer;
private BlockingQueue<IndexContextDTO> blockingQueue = new LinkedBlockingQueue<IndexContextDTO>(
500);
/**
*
*/
public AsynchronousThread() {
super("AsynchronousThread");
}
#PostConstruct
public void init() {
Integer internalQueueSize = 100;
this.blockingQueue = new LinkedBlockingQueue<>(internalQueueSize);
this.start();
}
#Override
public void run() {
while (true) {
// Do stuff
}
}
public void putInQueue(IndexContextDTO message) {
try {
this.blockingQueue.put(message);
} catch (InterruptedException interruptedException) {
// This exception will be thrown in very rare case.
LOGGER.error("An error while putting message in the queue. "
+ message, interruptedException);
}
}
}
So I want to intercept the unhandled exceptions and I am doing this by:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
//MY CUSTOM CODE TO SEND LOGS
System.exit(2);
}
});
Is there anyway I can execute my custom code and then resume normal way it handles these exceptions? I believe I am getting some hanging issues since System.exit doesn't seem to be working reliably.
You have to get the default handler first. Then intercept and send the error too the handler. System.exit... is a bad idea.
So first you create a custom exceptionhandler like you did:
public class CustomExceptionHandler implements Thread.UncaughtExceptionHandler {
private final Thread.UncaughtExceptionHandler defaultUEH;
public CustomExceptionHandler(Thread.UncaughtExceptionHandler defaultUEH) {
this.defaultUEH = defaultUEH;
}
#Override
public void uncaughtException(Thread thread, Throwable ex) {
String stackTrace = Log.getStackTraceString(ex);
String time = new Date(System.currentTimeMillis()).toString();
String message = ex.getMessage();
// send logs...
defaultUEH.uncaughtException(thread, ex);
}
}
So basically in your onCreate method (best used in a custom Application class to have it fall all parts) set the default exception handler if not already set (check not needed in Application):
Thread.UncaughtExceptionHandler defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
if (!(defaultUEH instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(defaultUEH));
}
I wrote it here (remove the BuildConfig.DEBUG check) implemented to directly start the email client. If there is no email client installed, you should catch the ActivityNotFoundException.
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
I'm working with javax.swing to make an aplication which generates forms from XML Schema (using JAXFront library) and stores the data filled by the user them into XML documents.
I have put try-catch-finally blocks when I need it, but I have a little problem catching exceptions when the main thread ends (The AWT threads are still running).
I have two classes which do the main work and other classes which aren't important for the question:
Main class: It has the following structure. Initializes the application and runs the main frame
public class Main {
public static void main(String[] args) {
readArgs(); // An INI file with the app config
Model model = initializeElements(args); // My model class
try {
MyFrame mfr = new MyFrame(title,model);
mfr.visualize(); // Assembling view and setting visible
} catch( Excepion e ) {
doCleanUp();
System.exit(-1);
}
}
}
Frame Class: Generates the view and listen events
public class MyFrame extends JFrame implements ActionListener,MenuListener {
// Some attributes
// Other mthods without importance
/**
* Compose the elements, add listeners and set visible the frame
*/
public void visualize() {
generateFormPanel();
setListeners();
validate();
setVisible(true);
}
public MyFrame(String title, Modele model) {
super(title);
createElementsUsing(model);
}
public void actionPerformed(ActionEvent e) {
// Code to manage events
}
}
Well, the problem is the following:
When the visualize function is exectuted from the main method, the view is generated and showed. At that moment is when I lose the control of the exceptions catching. Then my question is if there are some way to catch the possible RuntimeExceptions throwed after this point.
I hope you understand my English and can answer the question.
Thanks in advance.
Simplest version is to set the default uncaught exception handler:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
// do something
}
});
But that catches uncaught exceptions thrown in other parts of the program aswell.
You could however catch only runtime exceptions thrown off the swing event dispatching thread using a proxy (See this page for more information, copied code from there):
class EventQueueProxy extends EventQueue {
protected void dispatchEvent(AWTEvent newEvent) {
try {
super.dispatchEvent(newEvent);
} catch (Throwable t) {
// do something more useful than: t.printStackTrace();
}
}
}
Now installing it like this:
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new EventQueueProxy());
After you have called visualize() the only thread running is the Swing/AWT event dispatch thread. If you want to catch any exceptions you will need to do so in any of your listener methods that are called on this thread e.g.
public void actionPerformed(ActionEvent e) {
try {
// Some code here
} catch(RuntimeException e) {
// Handling code here
}
}
To prevent boilerplate you can have this code in a super class.
Note that you can also set a default uncaught exception handler if you want to catch anything not already dealt with by the Swing/AWT thread.
Note also that in general it is best practice to not catch subclasses of RuntimeException if you can avoid it.
Try adding:
setDefaultCloseOperation(EXIT_ON_CLOSE);
to MyFrame constructor. Not sure though, but worth trying.