Hi,
I'm in the process of migrating our Spring application from ancient
Wicket 1.5 to shiny new Wicket 7.10 (along with upgrading ~100 Maven
dependencies to their latest version and moving to JDK 9.0.4 ...). I did
the Wicket upgrade in two separate steps (1.5->6, 6 -> 7) and while the
Wicket 6.x version of our application worked without (obvious) issues,
one of our pages is crashing in the Wicket 7.10 version because an
internal sanity check gets tripped when the LazyInitProxyFactory tries
to proxy one of our Spring beans.
The code of the Spring bean that fails to be proxied in Wicket 7.x
(which uses CGLIB 3.1 while Wicket 6.0.29 used CGLIB 2.2.2) looks
similar to this:
public class SomeBean {
private static final AtomicLong INSTANCE_COUNTER = new
AtomicLong(0); // <<< DEBUG CODEto track instances
private static final Logger LOG =
org.apache.logging.log4j.LogManager.getLogger(SomeClass.class);
private final Map<stuff,stuff> registeredStuff=new HashMap<>();
private long id;
public SomeClass() {
this.id = INSTANCE_COUNTER.incrementAndGet();
registerStuff();
}
void registerStuff() {
LOG.error("=== registerStuff( ID = "+id+") called ===",new
Exception("dummy"));
register(...);
register(...);
// more
}
private void register(stuff) {
if ( registeredStuff.contains( stuff ) ) {
throw new IllegalArgumentException("stuff already
registered");<<< sanity check that gets tripped with CGLIB 3.3 since the
map is already populated
}
registeredStuff.put(stuff);
}
}
The difference between CGLIB 2.2.2 and CGLIB 3.1 is that the code in
LazyInitProxyFactory creates an uninitialized instance of the proxy
target when CGLIB 2.x is being used but CGLIB 3.x seems to copy the
field values from the proxy target and just invoke the registerStuff()
method without newly assigning the private fields.
At least this is what I could see through the "this.id =
INSTANCE_COUNTER.incrementAndGet();" line in my constructor ; on CGLIB
2.x the proxied instance has a new 'id' value while on CGLIB 3.1 the
proxied instance has the same ID value as the proxy target.
=== Wicket 6.x ===
2018-02-28 13:47:40,352 ERROR [main]
com.vodecc.voipmng.boundary.wicket.alarming.conditions.ConditionFactory:80
- === registerDefaultHandlers( ID = 1) called ===
java.lang.Exception: dummy
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.registerDefaultHandlers(ConditionFactory.java:80)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.<init>(ConditionFactory.java:69)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.<clinit>(ConditionFactory.java:59)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method) ~[?:?]
--
2018-02-28 13:47:40,376 ERROR [main]
com.vodecc.voipmng.boundary.wicket.alarming.conditions.ConditionFactory:80
- === registerDefaultHandlers( ID = 2) called ===
java.lang.Exception: dummy
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.registerDefaultHandlers(ConditionFactory.java:80)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.<init>(ConditionFactory.java:69)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method) ~[?:?]
at
jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
~[?:?]
--
2018-02-28 13:48:08,889 ERROR [http-nio-8080-exec-1]
com.vodecc.voipmng.boundary.wicket.alarming.conditions.ConditionFactory:80
- === registerDefaultHandlers( ID = 3) called ===
java.lang.Exception: dummy
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.registerDefaultHandlers(ConditionFactory.java:80)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.<init>(ConditionFactory.java:69)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
WICKET_com.vodecc.voipmng.boundary.wicket.alarming.conditions.ConditionFactory$$EnhancerByCGLIB$$b957aaed.<init>(<generated>)
[cglib-2.2.2.jar:?]
at
jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method) ~[?:?]
=== Wicket 7.x ===
2018-02-28 13:40:22,710 ERROR [main]
com.vodecc.voipmng.boundary.wicket.alarming.conditions.ConditionFactory:80
- === registerDefaultHandlers( ID = 1) called ===
java.lang.Exception: dummy
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.registerDefaultHandlers(ConditionFactory.java:80)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.<init>(ConditionFactory.java:69)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.<clinit>(ConditionFactory.java:59)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method) ~[?:?]
--
2018-02-28 13:40:22,734 ERROR [main]
com.vodecc.voipmng.boundary.wicket.alarming.conditions.ConditionFactory:80
- === registerDefaultHandlers( ID = 2) called ===
java.lang.Exception: dummy
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.registerDefaultHandlers(ConditionFactory.java:80)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
com.vodecc.voipmng.boundary.wicket.alarms.conditions.ConditionFactory.<init>(ConditionFactory.java:69)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method) ~[?:?]
at
jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
~[?:?]
--
2018-02-28 13:40:58,994 ERROR [http-nio-8080-exec-7]
com.vodecc.voipmng.boundary.wicket.alarming.conditions.ConditionFactory:80
- === registerDefaultHandlers( ID = 2) called ===
java.lang.Exception: dummy
at
com.vodecc.voipmng.boundary.wicket.alarming.conditions.ConditionFactory.registerDefaultHandlers(ConditionFactory.java:80)
[classes/:5.4.0-jdk9-SNAPSHOT]
at
com.vodecc.voipmng.boundary.wicket.alarming.conditions.Wicket_Proxy_ConditionFactory$$FastClassByCGLIB$$6aba25f8.invoke(<generated>)
[cglib-3.1.jar:5.4.0-jdk9-SNAPSHOT]
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
[cglib-3.1.jar:?]
at
org.apache.wicket.proxy.LazyInitProxyFactory$AbstractCGLibInterceptor.intercept(LazyInitProxyFactory.java:351)
[wicket-ioc-7.10.0.jar:7.10.0]
Unfortunately it seems neither the CGLIB nor the ASM guys keep track of
their changes in a changelog/migration guide so I was unable to figure
out the root cause of this change in behaviour.
Any ideas ?
Thanks,
Tobias