|
....this must only occur in some situations because i don't recall anyone noticing this problem before ?
the vresion we use is not unknown, it is ASM 1.5.3
Thanks for the version feedback.
I was taking 3.2.0.ga and replacing the hibernate3.jar that Spring provided to bring the latest bug fixes up to date when I noticed the problem. Since the JAR that ships from Spring works fine (previous RC to 3.2) and your stuff works fine independently, I should just stick with the Spring shipped release. The ASM versions each uses are much different so I'm scratching my head. However, I would like to use 3.2.0ga so if I find something useful, I'll comment back. So which version of CGLIB is spring using then?
Thank you for the replies. I have been looking into this further and although the Jars are different, using the JAR from Spring works with Hibernate 3.2.0rc4 (?). It looks like our encrypted custom class loader worked fine in Spring 1.x but not with 2. Initially it pointed at this issue. I believe this is just a change in Spring 2 that we have to account for. Thank you for the feedback. I think this link is realitve to my issue but not sure yet: http://opensource.atlassian.com/projects/spring/browse/SPR-2156 Hi, I encountered this issue when trying to package hibernate-3.3.2 for Gentoo Linux
I have discovered that using cglib-2.1.3 and asm-1.5.3 works correctly. This is based on a simple example that just generates 1 record in to the database (of only 1 table). Therefore as of yet I can not confirm whether these libraries will work in general. I should note that Gentoo is a source based linux distro and as such packages all third party libraries separately, downloading and compiling the source that are available on upstream websites, therefore the jars that I use may not be the exact versions used within the hibernate release. We check API compatibility and SLOT ( mechanism for installing different version of an package separately ) when necessary. The following is the error trace that I receive when running my example using I am happy to provide the example code if required. But will warn you that It is an adaption of the first stages of the hibernate tutorial ( so not advanced at all ) Initial SessionFactory creation failed.java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V Exception in thread "main" java.lang.ExceptionInInitializerError at org.javacrm.core.HibernateUtil.<clinit>(HibernateUtil.java:33) at org.javacrm.Main.createAndStoreTable(Main.java:45) at org.javacrm.Main.main(Main.java:37) Caused by: java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V at net.sf.cglib.core.ClassEmitter.begin_class(ClassEmitter.java:63) at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:173) at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:215) at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145) at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:117) at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:108) at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:64) at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.getProxyFactory(CGLIBLazyInitializer.java:107) at org.hibernate.proxy.pojo.cglib.CGLIBProxyFactory.postInstantiate(CGLIBProxyFactory.java:43) at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:162) at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:135) at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTup doesn't change the fact that it's asm is binary incompatible. How do they test hibernate in spring2 testsuite ? must have the same issue.
Alistair, I'm doing something very similar to you -- I'm integrating a source build of hibernate, and I'm also using that version of hibernate in a spring source build.
Spring uses the cglib-nodep artifact, which takes asm 1.5.3 and repackages it inside cglib as net.sf.cglib.asm. Spring itself uses ASM 2.2.3 in a couple of places and uses it unchanged from their stock distribution. This private version of asm is used only by cglib and amounts to a private static dependency. I've started work on a hibernate patch that uses the asm inside the cglib package, but I haven't finished it yet (probably be done early of next week). Since Hibernate uses 1.5.3 ASM and cglib uses 1.5.3 ASM, it should work with only source changes. I've finished the patch work -- basically I changed instances of "import org.objectweb.asm." to "import net.sf.cglib.asm" and used the cglib-nodep.jar instead of cglib.jar. Once this is done, the build completes normally and all unit tests that passed before the change pass after it.
After this, Hibernate and Spring can share a dependency on cglib-nodep without further conflict. I didn't bother to make a patch since the required changes are pretty obvious and I don't think Hibernate really wants to change their dependencies. If that's an incorrect assumption, I'd be happy to make a formal patch. Here's the patch I did for this. In addition, you'll need to replace cglib-2.1.3.jar in your lib/ directory with cglib-nodep-2.1.3.
My question still stands:
"doesn't change the fact that it's asm that is binary incompatible. How do they test hibernate in spring2 testsuite ? must have the same issue." Spring's tests don't exercise any part of Hibernate that uses cglib, and cglib is where the ASM incompatibility is. They test against a precompiled Hibernate jar and don't import any of the Hibernate classes that import org.objectweb.asm directly; i.e., classes in the patch (org/hibernate/bytecode/cglib/CglibClassTransformer.java, org/hibernate/bytecode/cglib/BytecodeProviderImpl.java, org/hibernate/tool/instrument/cglib/InstrumentTask.java). That's why it's not a problem for them. If they had any test that did in fact touch those classes, it would break (and if I change a Spring test to do that, it fails to compile).
As far as I can tell, there is no difference between the hibernate3.jar included with Spring and the jar distributed from hibernate.org. I just noticed that the asm faq has the solution to this problem http://asm.objectweb.org/doc/faq.html
15 How to resolve conflicts between different ASM API versions available in a global classpath or within the same ClassLoader? Tools and frameworks that are using ASM for bytecode processing (e.g. Hibernate, CGLIB, AspectWerkz) should repackage ASM code within their own name space. This can be automated with Jar Jar Links tool. http://tonicsystems.com/products/jarjar/ ----------------- Jar Jar Links is a utility that makes it easy to repackage Java libraries and embed them into your own distribution. This is useful for two reasons: * You can easily ship a single jar file with no external dependencies. * You can avoid problems where your library depends on a specific version of a library, which may conflict with the dependencies of another library. ... Jar Jar Links includes an Ant task (com.tonicsystems.jarjar.JarJarTask) that extends the built-in Jar task. The normal zipfileset element is used to embed jar files. A new rule element is added which uses wildcards patterns to rename the embedded class files. Bytecode transformation (via ASM) is used to change references to the renamed classes, and special handling is provided for moving resource files and transforming string literals. Jar Jar Friendly Libraries: include ASM ... so it doesnt seem like any source code changes are needed ! Would it be possible to implement this in the hibernate build process so that it doesnt conflict with other versions of asm that the user may need (its not just a hibernate-spring problem) I'll look into making the change so that hibernate can be used with Spring 2.x.
I might be wrong but I think we tried that and bytecode enhanced classes had issues, maybe it worths a second look
I am absolutely against repackaging within Hibernate. And in fact repackaging within cglib is at best a band-aid with one side of its stickiness worn off; as soon as you have two versions of cglib doing this repackaging you have the same issue.
Generally speaking, as a container it is Spring's responsibility to isolate its implementation details from its users. This is *exactly* the reason that app servers do this re-packaging of libraries all the time. As for Hibernate users, there is a trivial work around: use javassist for the bytecode provider. Long term, as soon as cglib has a release using asm 2.x (it looks like cvs currently has asm 2.2.1) we will move to that. Steve, I want to understand where you're coming from. Are you saying that it's Spring's responsibility to repackage their libraries, since they're a framework, while Hibernate doesn't have to since it's not? I think I understand the philosophical point, but as a practical matter, this would make life a lot easier for Spring users. What am I missing?
Also, what if using javassist isn't an option for a Hibernate user? (Company policy of Officially Approved open source, license problems, etc.) >> Are you saying that it's Spring's responsibility to repackage their libraries
Yes, in so far as those implementation details leak out to users and effect them. In fact, in contrast, Hibernate goes out of its way to not expose the underlying bytecode provider library to user, instead using a contract or facade. >> since they're a framework, while Hibernate doesn't have to since it's not Spring is *not* a framework. They have hood-winked you ;) They are a container, just like any app server. Of course to admit to that takes away their edge. >> Also, what if using javassist isn't an option for a Hibernate user? (Company policy of Officially Approved open source, license problems, etc.) Well, I'd say you might want to reconsider that policy. And licensing is not a valid argument since javassist is distributed under LGPL just as Hibernate; you can't take issue over the LGPL in relation to one library, but not another... We will upgrade to CGLB 2.2 as soon as it is ready to go. CGLIB 2.2 is set to use ASM 2.2.x (I think 2.2.1 currently) which then should alleviate this condition. Gail is investigating this to make sure we are correct in this understanding. I see where you're coming from now. Thanks for talking slowly and using big words for me. :)
I also "walk softly and carry a big stick" ;)
Depending on the options used in spring the above workaround may or may not work, if you use the ClassPathScanner or an option that depends on using the ClassPath scanner the solution doesnt work. (see http://jira.springframework.org/browse/SPR-3856 for more details)
The Spring Team fixed the problem in Spring 2.5 by repackaging ASM, so the real solution is to upgrade to spring 2.5 Andy Bailey http://www.hazlorealidad.com Quote from Juergen Hoeller (from the above jira report) We do repackage ASM for Spring 2.5 now (as part of spring.jar and spring-core.jar), avoiding conflicts with other ASM versions as well as making it easier to use Spring's component scanning feature (no need for adding any asm-* jars for those purposes anymore). This required a revision of Spring's "core.type" package, using ASM internally now, with no ASM artifacts exposed publically - meaning that other packages (other Spring framework packages as well as third-party packages) can use "core.type" without being tied to the original or repackaged ASM location. Juergen |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
workaround: use javassist as hibernates bytecode provider.
..and really bad that asm/cglib decided to become binary incompatible ;(