-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi,
I'm using ZK 8.0 and Hibernate in my project. I use MVVM and form binding.
The properties of my ViewModel are Hibernate-managed beans. So they can be proxies. When I use form binding, ZK tries to transform these properties to proxies.
This can be a problem because au proxy can't be tunred into a proxy a second time as both Hibernate and ZK use Javassist.
So I have this exception:
java.lang.RuntimeException: duplicate method: setHandler in com.company.package.MyClass_$$_jvst8dc_10_$$_jvst8dc_1d
javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:515)
javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:492)
javassist.util.proxy.ProxyFactory.createClass1(ProxyFactory.java:428)
javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:400)
org.zkoss.bind.proxy.ProxyHelper.createProxyIfAny(ProxyHelper.java:88)
org.zkoss.bind.proxy.BeanProxyHandler.invoke(BeanProxyHandler.java:163)
com.company.package.MyOtherClass_$$_jvst8dc_1b.getMyClass(MyOtherClass_$$_jvst8dc_1b.java)
com.company.package.MyOtherClass.equals(MyOtherClass.java:38)
java.util.ArrayList.indexOf(ArrayList.java:298)
org.zkoss.zul.ListModelList.indexOf(ListModelList.java:247)
org.zkoss.zul.ListModelList.fireSelectionEvent(ListModelList.java:458)
org.zkoss.zul.AbstractListModel.addToSelection(AbstractListModel.java:125)
org.zkoss.bind.converter.sys.ListboxSelectedItemConverter.coerceToUi(ListboxSelectedItemConverter.java:48)
org.zkoss.bind.impl.LoadPropertyBindingImpl.load(LoadPropertyBindingImpl.java:74)
org.zkoss.bind.impl.PropertyBindingHandler.doLoadBinding(PropertyBindingHandler.java:133)
org.zkoss.bind.impl.PropertyBindingHandler.doLoad(PropertyBindingHandler.java:334)
org.zkoss.bind.impl.BinderImpl.loadComponentProperties0(BinderImpl.java:2307)
org.zkoss.bind.impl.BinderImpl.loadComponent0(BinderImpl.java:2276)
org.zkoss.bind.impl.BinderImpl.loadComponent0(BinderImpl.java:2281)
org.zkoss.bind.impl.BinderImpl.loadComponent0(BinderImpl.java:2281)
org.zkoss.bind.impl.BinderImpl.loadComponent0(BinderImpl.java:2281)
org.zkoss.bind.impl.BinderImpl.loadComponent(BinderImpl.java:2215)
org.zkoss.bind.BindComposer$BinderKeeper$Loader.load(BindComposer.java:564)
org.zkoss.bind.BindComposer$BinderKeeper.loadComponentForAllBinders(BindComposer.java:540)
org.zkoss.bind.BindComposer.doAfterCompose(BindComposer.java:188)
org.zkoss.zk.ui.impl.UiEngineImpl.doAfterCompose(UiEngineImpl.java:588)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:924)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:870)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:745)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:709)
org.zkoss.zk.ui.impl.UiEngineImpl.createComponents(UiEngineImpl.java:1124)
org.zkoss.zk.ui.impl.AbstractExecution.createComponents0(AbstractExecution.java:283)
org.zkoss.zk.ui.impl.AbstractExecution.createComponents(AbstractExecution.java:271)
org.zkoss.zul.Include.afterCompose(Include.java:486)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:922)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:870)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:745)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:709)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:916)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:870)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:745)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:709)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:916)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:870)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:745)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:709)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:916)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:870)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:745)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:814)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:767)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:709)
org.zkoss.zk.ui.impl.UiEngineImpl.execNewPage0(UiEngineImpl.java:452)
org.zkoss.zk.ui.impl.UiEngineImpl.execNewPage(UiEngineImpl.java:358)
org.zkoss.zk.ui.http.DHtmlLayoutServlet.process(DHtmlLayoutServlet.java:217)
org.zkoss.zk.ui.http.DHtmlLayoutServlet.doGet(DHtmlLayoutServlet.java:136)
javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
I can't tell Hibernate to use CGlib instead of Javassist, because that feature is deprecated.
I really don't know how I could solve this.
Thank you!
I found a workaround to this problem. The thing is you can't have proxies in your ViewModel when using form binding in ZK 8.
So I had to deproxy my Hibernate managed beans, using this utility method:
public <T> T initializeAndUnproxy(T o, boolean initializeAndUnproxyFields) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
if (o == null) {
return null;
}
Hibernate.initialize(o);
if (o instanceof HibernateProxy) {
o = (T)((HibernateProxy)o).getHibernateLazyInitializer().getImplementation();
}
if (initializeAndUnproxyFields) {
for (Method method : o.getClass().getDeclaredMethods()) {
if (method.getName().startsWith("get") && method.getParameterTypes().length == 0
&& isHibernateManaged(method.getReturnType())) {
Object valueOfField = method.invoke(o);
valueOfField = initializeAndUnproxy(valueOfField, false);
Method setter = o.getClass().getMethod("s" + method.getName().substring(1),
method.getReturnType());
setter.invoke(o, valueOfField);
}
}
}
return o;
}
The isHibernateManaged() method looks like this, I couldn't find something better (suggestions welcome):
private boolean isHibernateManaged(Class<?> type) {
return type.getPackage().getName().equals("com.company.something.beans");
}
In your ViewModel, you use it like this:
bean = HibernateUtils.initializeAndUnproxy(bean, true);
Set<OtherBean> unproxiedOtherBeans = new TreeSet<OtherBean>();
for (OtherBean otherBean : bean.getOtherBeans()) {
OtherBean unproxiedOtherBean = HibernateUtils.initializeAndUnproxy(otherBean , true);
unproxiedOtherBeans.add(unproxiedOtherBean );
}
bean.getOtherBeans().clear();
bean.getOtherBeans().addAll(unproxiedOtherBeans);
So your bean property is not a proxy anymore, and its otherBeans collection is not filled with proxies either.
All this could be wrapped in a helper class to reduce the amount of code needed in the ViewModel, but it works.
Asked: 2015-08-21 13:41:31 +0800
Seen: 76 times
Last updated: Sep 16 '15
Class Level Constraint BeanValidator
Using MVVM, how can I delay bean setters calls?
How to configure quartz to use Hibernate in Zk app? [closed]
zk hibernate session per conversation
where to put @Transactional (Hibernate Spring)
Is ZK compatible with hibernate 4.0
use Hibernate standard methods to manage Sessions ??