Steps to Reproduce
create an .ear file with 2 or more zk war files (using each zkbind-impl.jar and a shared zkbind-api.jar outside the war files)
deploy on websphere/wildfly
load a zk page form both war files (MVVM)
isolated reproducing steps
extract/run the attachment zkbind-api-multiple-wars.zip
javac src/zk/test/Main.java java -cp src/ zk.test.Main
Current Result
first page works
loading the second page produces a class loading exception:
error on websphere:
[ERROR ] SRVE0777E: Exception thrown by application class 'org.zkoss.bind.impl.BinderImpl.newCommandBinding:1,099' java.lang.LinkageError: loader constraint violation in interface itable initialization for class org.zkoss.bind.impl.BindingImpl: when selecting method 'org.zkoss.bind.Binder org.zkoss.bind.sys.Binding.getBinder()' the class loader com.ibm.ws.classloading.internal.AppClassLoader @24d9588b for super interface org.zkoss.bind.sys.Binding, and the class loader com.ibm.ws.classloading.internal.AppClassLoader @24ecd8af of the selected method's class, org.zkoss.bind.impl.BindingImpl have different Class objects for the type org.zkoss.bind.Binder used in the signature (org.zkoss.bind.sys.Binding is in unnamed module of loader com.ibm.ws.classloading.internal.AppClassLoader @24d9588b, parent loader com.ibm.ws.classloading.internal.GatewayClassLoader @4cfc48bf; org.zkoss.bind.impl.BindingImpl is in unnamed module of loader com.ibm.ws.classloading.internal.AppClassLoader @24ecd8af, parent loader com.ibm.ws.classloading.internal.AppClassLoader @24d9588b) at org.zkoss.bind.impl.BinderImpl.newCommandBinding(BinderImpl.java:1099) at org.zkoss.bind.impl.BinderImpl.addCommandBinding(BinderImpl.java:1480) at org.zkoss.bind.impl.AnnotateBinderHelper.processCommandBinding(AnnotateBinderHelper.java:179) at org.zkoss.bind.impl.AnnotateBinderHelper.processComponentBindings0(AnnotateBinderHelper.java:119) at org.zkoss.bind.impl.AnnotateBinderHelper.processAllComponentsBindings(AnnotateBinderHelper.java:87) at org.zkoss.bind.impl.AnnotateBinderHelper.initComponentBindings(AnnotateBinderHelper.java:73) at org.zkoss.bind.AnnotateBinder.initAnnotatedBindings(AnnotateBinder.java:74) at org.zkoss.zkmax.bind.impl.AnnotateBinderEx.initAnnotatedBindings(AnnotateBinderEx.java:35) at org.zkoss.bind.BindComposer.doAfterCompose(BindComposer.java:229) at org.zkoss.zk.ui.impl.UiEngineImpl.doAfterCompose(UiEngineImpl.java:622)
similar error on wildfly:
18:44:26,999 ERROR [io.undertow.request] (default task-4) UT005023: Exception handling request to /scopeweb/: java.lang.LinkageError: loader constraint violation in interface itable initialization for class org.zkoss.bind.impl.BindingImpl: when selecting method 'org.zkoss.bind.Binder org.zkoss.bind.sys.Binding.getBinder()' the class loader 'deployment.testEAR-1.0.0-SNAPSHOT.ear' @165f19bd for super interface org.zkoss.bind.sys.Binding, and the class loader 'deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war' @1b821d90 of the selected method's class, org.zkoss.bind.impl.BindingImpl have different Class objects for the type org.zkoss.bind.Binder used in the signature (org.zkoss.bind.sys.Binding is in unnamed module of loader 'deployment.testEAR-1.0.0-SNAPSHOT.ear' @165f19bd, parent loader 'app'; org.zkoss.bind.impl.BindingImpl is in unnamed module of loader 'deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war' @1b821d90, parent loader 'app') at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.bind.impl.BinderImpl.newCommandBinding(BinderImpl.java:1099) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.bind.impl.BinderImpl.addCommandBinding(BinderImpl.java:1480) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.bind.impl.AnnotateBinderHelper.processCommandBinding(AnnotateBinderHelper.java:179) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.bind.impl.AnnotateBinderHelper.processComponentBindings0(AnnotateBinderHelper.java:119) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.bind.impl.AnnotateBinderHelper.processAllComponentsBindings(AnnotateBinderHelper.java:87) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.bind.impl.AnnotateBinderHelper.initComponentBindings(AnnotateBinderHelper.java:73) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.bind.AnnotateBinder.initAnnotatedBindings(AnnotateBinder.java:74) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.zkmax.bind.impl.AnnotateBinderEx.initAnnotatedBindings(AnnotateBinderEx.java:35) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.bind.BindComposer.doAfterCompose(BindComposer.java:229) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.zk.ui.impl.UiEngineImpl.doAfterCompose(UiEngineImpl.java:622) at deployment.testEAR-1.0.0-SNAPSHOT.ear.scopeweb.war//org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:947)
same error in a simulated environment:
Exception in thread "main" java.lang.LinkageError: loader constraint violation in interface itable initialization for class org.zkoss.bind.impl.BindingImpl: when selecting method 'org.zkoss.bind.Binder org.zkoss.bind.sys.Binding.getBinder()' the class loader 'shared' @7440e464 for super interface org.zkoss.bind.sys.Binding, and the class loader 'war-B' @78308db1 of the selected method's class, org.zkoss.bind.impl.BindingImpl have different Class objects for the type org.zkoss.bind.Binder used in the signature (org.zkoss.bind.sys.Binding is in unnamed module of loader 'shared' @7440e464, parent loader 'app'; org.zkoss.bind.impl.BindingImpl is in unnamed module of loader 'war-B' @78308db1, parent loader 'shared' @7440e464) at java.base/java.lang.Class.getDeclaredConstructors0(Native Method) at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3137) at java.base/java.lang.Class.getConstructor0(Class.java:3342) at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553) at zk.test.Main.createCommandBinding(Main.java:35) at zk.test.Main.main(Main.java:24)
Expected Result
no classloading erros, possible to use MVVM in modular environment
Debug Information
- There's a circular dependency between zkbind-api.jar and zkbind-impl.jar
zkbind-impl.jar : org.zkoss.bind.impl.BindingImpl
implements -> zkbind-api.jar : org.zkoss.bind.sys.Binding
Binding.getBinder() -> returns org.zkoss.bind.Binder which is an interface inside zkbind-impl.jar
zkbind-impl.jar -> zkbind-api.jar -> zkbind-impl.jar (circle)
Workaround
manually move org.zkoss.bind.Phase and org.zkoss.bind.sys.ConditionType from zkbind-impl.jar to zkbind-api.jar
Proposed solution
when packaging jar, put org.zkoss.bind.Phase and org.zkoss.bind.sys.ConditionType into zkbind-api.jar instead of zkbind-impl.jar