0

LongUIOperation Executions.deactivate null pointer exception

asked 2017-12-11 19:26:43 +0800

etorrente gravatar image etorrente
0 1

updated 2017-12-11 19:33:01 +0800

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;
}

... ...

delete flag offensive retag edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2018-01-02 10:24:57 +0800

MDuchemin gravatar image MDuchemin
2560 1 6
ZK Team

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.

link publish delete flag offensive edit
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow
1 follower

RSS

Stats

Asked: 2017-12-11 19:26:43 +0800

Seen: 18 times

Last updated: Jan 02 '18

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More