Moving from ZK event thread to the recommended servlet thread. Part I.
As you already imagined, migrating code to the recommended servlet thread is a nightmare. Anyway, since ZK deprecated the event thread, I thought reasonable to start the migration now. Here are some issues I encountered while doing so.
Close without saving?
Are you capturing the onClose
event of a container to prevent user from exiting without saving its content?
This piece of code does capture the event, ask user if really want to exit loosing modifications. If user says no, the event method stopPropagation()
is called and the tab remains open.
Tab tab = container.getLinkedTab(); tab.addEventListener(9000, Events.ON_CLOSE, new EventListener() { @Override public void onEvent(Event event) throws Exception { if(modified) { if(!ZkossUtils.confirmMessage(ElLabel.getLabel("lCloseWithoutSaving"))) { event.stopPropagation(); } } } }); ... public static boolean confirmMessage(String message) { if(Messagebox.show(message, ElLabel.getLabel("lQuestion"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION) == Messagebox.OK) { return true; } return false; }
With servlet thread this code no longer works. The method stopPropagation()
gets never called. Messagebox.show()
returns immediately and there is no chance that confirmMessage()
returns true.
We need to make some changes. In the example I choose commons-chain
, but Runnable
is also a choice.
final Tab tab = container.getLinkedTab(); tab.addEventListener(9000, Events.ON_CLOSE, new EventListener() { @Override public void onEvent(final Event event) throws Exception { if(modified) { // check whether tab content has been changed event.stopPropagation(); ZkossUtils.confirmMessage(ElLabel.getLabel("lCloseWithoutSaving"), new Command() { @Override public boolean execute(Context context) throws Exception { tab.close(); return Command.PROCESSING_COMPLETE; } }); } } }); ... public static void confirmMessage(String message, final Command command) { Messagebox.show(message, ElLabel.getLabel("lQuestion"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION, new EventListener () { @Override public void onEvent(Event event) throws Exception { Context ctx = new ContextBase(); switch ((Integer) event.getData()) { case Messagebox.OK: command.execute(ctx); break; } } }); }
First modification is to use Messagebox's EventListener. There we put the code we want to execute when the OK button gets clicked.
The onClose
event has changed some more. Fist, we call stopPropagation()
when modified
is true. This ensures the tab will remain open. Then, we close the tab. Doing so programmatically prevents from entering an endless loop. Notice that in real-world applications, the tab may have its own listeners and perform some stuff.
Before you get mad with modal windows
Setting the modal state. With the event thread enabled you could do setMode("modal")
before attaching the window to the page. With the servlet thread that's no longer true. It will throw a not attached exception
. So, if you set the window mode somewhere before setPage(page)
, simply remove the call to setMode()
and use doModal()
once the page has been set.