Post-13.2 Plugin hot deploy issues

Good news: the old hot deploy compile issues seem to be gone.

Bad news: there is a new issue - all seems to be fine, but when I go to open the hot-deployed screen, sometimes (more often than not), I get:

ClassCastException: class com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen cannot be cast to class com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen (com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen is in unnamed module of loader com.haulmont.cuba.core.sys.javacl.JavaClassLoader$FileClassLoader @3251b3b3; com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @54227100)

Better formatted:

Caused by: java.lang.ClassCastException: class com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen cannot be cast to class com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen (com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen is in unnamed module of loader com.haulmont.cuba.core.sys.javacl.JavaClassLoader$FileClassLoader @43198314; com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @54227100)
	at com.medflex.medflexj.web.screens.invoice.InvoiceEdit.onSetResponsibilityBtnClick(InvoiceEdit.java:230) ~[medflex-web-0.1-SNAPSHOT.jar:na]
	at com.haulmont.bali.events.EventHub.publish(EventHub.java:170) ~[cuba-global-7.2.3.jar:7.2.3]
	at com.haulmont.cuba.web.gui.components.WebAbstractComponent.publish(WebAbstractComponent.java:100) ~[cuba-web-7.2.3.jar:7.2.3]
	at com.haulmont.cuba.web.gui.components.WebButton.buttonClicked(WebButton.java:70) ~[cuba-web-7.2.3.jar:7.2.3]
	at com.haulmont.cuba.web.widgets.CubaButton.fireClick(CubaButton.java:76) ~[cuba-web-widgets-7.2.3.jar:na]
	at com.vaadin.ui.Button$1.click(Button.java:57) ~[vaadin-server-8.9.2-5-cuba.jar:8.9.2-5-cuba]
	... 43 common frames omitted

Of course restarting the server, the problem goes away. This is a hot deploy problem only.

Hi! Could you enable debug logs (CUBA -> Advanced -> Enable DEBUG Logging Level), reproduce the problem, and attach idea.log file (Help -> Show Logs in ...).

Sure thing, here we go. (There’s nothing suspicious in idea.log, but here it is anyway)

idea.log (982.9 KB)

The weirdest part of this is the Exception itself:

class com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen 
cannot be cast to 
class com.medflex.medflexj.web.screens.invoice.SetResponsibilityScreen

… they’re the same class! I’m not even sure why there’s a cast being attempted, or where; obviously some internals of the hot deploy process?

they’re the same class!

Actually, they are not the same :slight_smile: The first is compiled during the hot deploy, and the second one is ‘initial’ class, that had been compiled before app is started. The problem is, that some class, I guess InvoiceEdit, references the old class. But, it also should be hot deployed, and I sure it is. So, try to also reopen InvoiceEdit, and the whole chain of dependent classes future cases.

Hmmm? I’m not sure what you mean.

I guess, you open your SetResponsibilityScreen screen from InvoiceEdit screen. InvoiceEdit class depends on SetResponsibilityScreen via some reference in code. So, when CUBA Studio hot deploys SetResponsibilityScreen, it also hot deploys InvoiceEdit. They together form a ‘chain of dependent classes’. For correct work of hot deploy, you should close all classes within this chain.
The exception looks like you don’t reopen InvoiceEdit screen.

This is true.

I wouldn’t say that necessarily. SRS is just a screen that’s opened from IE via screenBuilders.editor() like any other screen you might open from a screen. So I’m not sure why the redeploy of IE is being triggered.

But yes, closing both screens and trying again does indeed make the hot deploy work.

This may need mentioned in documentation somewhere, since it’s far from intuitive.

So I’m not sure why the redeploy of IE is being triggered.

Because Java works in such way. We cannot replace the dependency class without replacing the dependent.

This may need mentioned in documentation somewhere, since it’s far from intuitive.

Good point, we will think about it.

Well my point is I don’t see where the dependency is coming from. It’s just a screen that’s opened via screenBuilders like any other screen. If that creates a dependency then any screen that is opened via screenBuilders has a dependency with the screen that opens it, but I haven’t seen this behavior before.

I suppose, your InvoiceEdit has such code:

screenBuilders.editor(SetResponsibility.class, this)
                .withScreenClass(SetResponsibilityScreen.class) // SetResponsibilityScreen.class brings dependency
                ...;

May be, you use SRS inside IE in a different way.

The easy rule is:
If class A has import B; in its code, it depends on class B.