-
FEATURED COMPONENTS
First time here? Check out the FAQ!
I'm using LongUIOperation custom implementation, but, sometimes, on
Executions.deactivate(getNativeDesktop());
I receive messagebox on screen and:
dic 11, 2017 11:09:42 AM org.zkoss.zk.ui.impl.UiEngineImpl handleError GRAVE: java.lang.NullPointerException at org.apache.catalina.connector.Request.notifyAttributeAssigned(Request.java:1528) at org.apache.catalina.connector.Request.setAttribute(Request.java:1514) at org.apache.catalina.connector.RequestFacade.setAttribute(RequestFacade.java:540) at org.zkoss.zk.ui.http.ExecutionImpl.setAttribute(ExecutionImpl.java:497) at org.zkoss.zk.ui.impl.Utils.getComponentInfos(Utils.java:120) at org.zkoss.zk.ui.impl.Utils.setComponentInfo(Utils.java:129) at org.zkoss.zk.ui.impl.AbstractUiFactory.newComponent(AbstractUiFactory.java:137) at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:919) at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:889) at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:776) at org.zkoss.zk.ui.impl.UiEngineImpl.access$800(UiEngineImpl.java:128) at org.zkoss.zk.ui.impl.UiEngineImpl$TemplateImpl.create(UiEngineImpl.java:2318) at org.zkoss.bind.impl.BindListitemRenderer.render(BindListitemRenderer.java:79) at org.zkoss.zul.Listbox$Renderer.render(Listbox.java:2769) at org.zkoss.zul.Listbox.doInitRenderer(Listbox.java:2584) at org.zkoss.zul.Listbox.onInitRender(Listbox.java:2537) at sun.reflect.GeneratedMethodAccessor2366.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3146) at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3077) at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:138) at org.zkoss.zk.ui.impl.UiEngineImpl.processEvent(UiEngineImpl.java:1846) at org.zkoss.zk.ui.impl.UiEngineImpl.process(UiEngineImpl.java:1618) at org.zkoss.zk.ui.impl.UiEngineImpl.endUpdate(UiEngineImpl.java:1222) at org.zkoss.zkex.ui.comet.CometServerPush.deactivate(CometServerPush.java:522) at org.zkoss.zk.ui.impl.DesktopImpl.deactivateServerPush(DesktopImpl.java:1596) at org.zkoss.zk.ui.Executions.deactivate(Executions.java:1011) at com.ims.web.ui.GenericViewModel.deactivateNativeDesktop(GenericViewModel.java:193) at com.ims.web.zk.ui.DesktopVMLongUIOperation.run(DesktopVMLongUIOperation.java:186) at java.lang.Thread.run(Unknown Source)
Use case example:
@Command
@Override
public void editBaseItem() throws Exception {
super.editBaseItem();
if(selectedBaseItem.getOid() == null){
initNewItem();
}
final String sessionID = getSessionID();
final StaffDailyAvailabilityVM instanceVM = this;
new DesktopVMLongUIOperation(this,win,Labels.getLabel("def.msg.refreshdata","Refresh data...")) {
@Override
protected void execute() throws InterruptedException {
try {
StaffDailyAvailabilityManager.evaluateStaffDailyAvailabilitySynch(selectedBaseItem, sessionID);
} catch (Exception e) {
logger.error(e,e);
}
}
protected void onCleanup() {
try {
//refresh clock time list
selectedBaseItem.getLastStaffDailyTimestampDTO();
if(selectedBaseItem.isErrorDetected()){
selectedBaseItem.setCertified(false);
}
BindUtils.postNotifyChange(null, null, instanceVM.getSelectedBaseItem(),"lastStaffDailyTimestampDTO");
BindUtils.postNotifyChange(null, null, instanceVM, "selectedBaseItem");
} catch (Exception e) {
logger.error(e,e);
}
};
}.start();
}
Here the code:
public abstract class DesktopVMLongUIOperation implements Runnable { protected static final Logger logger = Logger.getLogger(DesktopVMLongUIOperation.class); private Thread thread; private AtomicBoolean cancelled = new AtomicBoolean(false); private Window win; private GenericViewModel genericViewModel;
public DesktopVMLongUIOperation(GenericViewModel genericViewModel){
this(genericViewModel,null,"");
}
public DesktopVMLongUIOperation(GenericViewModel genericViewModel, Window win, String busyMsg){
this.win = win;
this.genericViewModel = genericViewModel;
try {
this.genericViewModel.enableServerPush(null);
if(win != null){
Clients.showBusy(win,busyMsg);
}
} catch (Exception e) {
logger.error(e,e);
}
}
/**
* asynchronous callback for your long operation code
* @throws InterruptedException
*/
protected abstract void execute() throws InterruptedException;
/**
* optional callback method when the task has completed successfully
*/
protected void onFinish() {};
/**
* optional callback method when the task has been cancelled or was interrupted otherwise
*/
protected void onCancel() {};
/**
* optional callback method when the task has completed with an uncaught RuntimeException
* @param exception
*/
protected void onException(RuntimeException exception) {
logger.error(exception,exception);
};
/**
* optional callback method when the task has completed (always called)
*/
protected void onCleanup() {};
/**
* set the cancelled flag and try to interrupt the thread
*/
public final void cancel() {
try {
cancelled.set(true);
if(thread != null){
thread.interrupt();
}
} catch (Throwable e) {
logger.error(e,e);
}
}
/**
* check the cancelled flag
* @return
*/
public final boolean isCancelled() {
return cancelled.get();
}
/**
* Checks if the task thread has been interrupted. Use this to check whether or not to exit a busy operation in case.
* @throws InterruptedException when the current task has been cancelled/interrupted
*/
protected final void checkCancelled() throws InterruptedException {
try {
if(Thread.currentThread() != this.thread) {
throw new IllegalStateException("this method can only be called in the worker thread (i.e. during execute)");
}
boolean interrupted = Thread.interrupted();
if(interrupted || cancelled.get()) {
cancelled.set(true);
throw new InterruptedException();
}
} catch (Throwable e) {
logger.error(e,e);
}
}
/**
* launch the long operation
*/
public final void start() {
try {
thread = new Thread(this);
thread.start();
} catch (Throwable e) {
logger.error(e,e);
}
}
@Override
public final void run() {
try {
try {
checkCancelled(); //avoid unnecessary execution
execute();
checkCancelled(); //final cancelled check before calling onFinish
genericViewModel.activateNativeDesktop();
logger.error("ACTIVATE: RUN");
onFinish();
} catch (InterruptedException e) {
try {
cancelled.set(true);
genericViewModel.activateNativeDesktop();
logger.error("ACTIVATE: INTERRUPT");
onCancel();
} catch (InterruptedException e1) {
throw new RuntimeException("interrupted onCancel handling", e1);
} catch (Exception e1) {
logger.error(e1,e1);
} finally {
try {
genericViewModel.deactivateNativeDesktop();
logger.error("DEACTIVATE: INTERRUPT");
} catch (Exception e1) {
logger.error(e1,e1);
}
}
} catch (RuntimeException rte) {
try {
genericViewModel.activateNativeDesktop();
logger.error("ACTIVATE: EXCEPTION");
onException(rte);
} catch (InterruptedException e1) {
throw new RuntimeException("interrupted onException handling", e1);
} catch (Exception e) {
logger.error(e,e);
} finally {
try {
genericViewModel.deactivateNativeDesktop();
logger.error("ACTIVATE: EXCEPTION");
} catch (Exception e) {
logger.error(e,e);
}
}
throw rte;
} catch (Exception e) {
logger.error(e,e);
} finally {
try {
genericViewModel.deactivateNativeDesktop();
logger.error("DEACTIVATE: RUN");
} catch (Exception e) {
logger.error(e,e);
}
}
} finally {
try {
genericViewModel.activateNativeDesktop();
logger.error("ACTIVATE: CLEANUP");
try {
if(win != null){
Clients.clearBusy(win);
}
} catch (Exception e) {
logger.error(e,e);
}
onCleanup();
} catch (InterruptedException e1) {
throw new RuntimeException("interrupted onCleanup handling", e1);
} catch (Exception e1) {
logger.error(e1,e1);
} finally {
try {
genericViewModel.deactivateNativeDesktop();
logger.error("DEACTIVATE: CLEANUP");
} catch (Exception e) {
logger.error(e,e);
}
}
}
}
}
And activate deactivate code from genericViewModel:
... ... public GenericViewModel(){ nativeDesktop = Executions.getCurrent().getDesktop(); }
... ...
public boolean activateNativeDesktop() throws Exception{
boolean res = false;
if(getNativeDesktop() != null && getNativeDesktop().isAlive()){
try {
Executions.activate(getNativeDesktop());
res = true;
} catch (Throwable e) {
logger.error(e,e);
throw(e);
}
}else{
throw new Exception("ZK native Desktop is null");
}
return res;
}
public boolean deactivateNativeDesktop() throws Exception{
boolean res = false;
if(getNativeDesktop() != null && getNativeDesktop().isAlive()){
try {
Executions.deactivate(getNativeDesktop());
res = true;
} catch (Throwable e) {
logger.error(e,e);
throw(e);
}
}else{
throw new Exception("ZK native Desktop is null");
}
return res;
}
... ...
Hi etorrente,
Which ZK / tomcat version are you running? Can you reproduce the exception on demand (is there a way to trigger it consistently)? If not, how often does it happen?
It looks like the exception happens during the components update phase of the desktop deactivation. While building components, it tries to set an attribute on the current request, which then tries to notify something, which fails with an NPE.
First thing I would do would be to set an exception breakpoint for NPE, and go up the stack to org.zkoss.zk.ui.impl.Utils.getComponentInfos(Utils.java:120) to check the content of the result variable being set into the COMPONENT_INFO attribute. In the same breakpoint, you might also want to check the value of Excecutions.getCurrent(), which might be null, and Executions.getCurrent.getDesktop() to see if it match the desktop saved in your GenericViewModel.
Asked: 2017-12-11 19:26:43 +0800
Seen: 18 times
Last updated: Jan 02 '18