Problem
You are getting an error along the following lines when running a custom component for LiveCycle ES and ES2:
"[com.adobe.
even though you know for sure that AChild is a child or implementor of AParent – for instance:
"com.adobe.idp.taskmanager.dsc.client.query.TaskRowImpl cannot be cast to com.adobe.idp.taskmanager.dsc.client.query.TaskRow"
Additionally:
-You have included the JAR files from LiveCycle’s deployment directories into your component JAR
-If you remove the Adobe JAR from your Custom Component’s JAR, you get a ClassDefNotFoundError.
Solution
-Remove the Adobe JARs from your custom component’s JAR
-Modify your component XML and add
Reason
This puzzling problem is to do simply with how different class loaders interact. To abstract over any proper LiveCycle classes, I will be talking about a fictitious Pan class.
# 1) About class loaders
A Pan is not a Pan when you have two different definitions of a Pan.
When you load a class called Pan with one class loader, and you load it again with a different class loader, they are different definitions in memory of a Pan.
So when you try to assign [a Pan instance from the first class loader] to [a Pan variable defined by the second class loader], the JVM will not match them up as being the same type of Pan – and you will get the unexpected ClassCastException.
-When the JVM is started, it uses a class loader to start loading all the classes it needs, along with the web application server.
-When the app server starts loading LiveCycle, it creates several class loaders – one for each EAR, for example; and within the EARs, one for each WAR, etc.
-Many different components are loaded by many different class loaders
When you deploy your custom component, it gets loaded by its own class loader. Here’s where it gets tricky.
# 2) Delegating class loaders
If you ask LiveCycle to give you a Pan via some API call, it will give you a Pan that one of its class loaders defined. When in your code you declare a variable to hold that Pan, you’re using your class loader’s Pan definition. A definition clash ensues.
Obviously you don’t want to load your own Pan when LiveCycle already has a definition for a Pan – remove the Adobe JARs that you included with your custom component. If you run the project now, you may get a ClassDefNotFoundError. Why?
If your class loader could not find a Pan of its own, it delegates finding the Pan up to the class loader that loaded it – the parent class loader. The parent class loader will ask your class loader what packages it needs to look in – this is specified in your component XML under the
At this point, either one of two things can happen:
-if you specified a package in component XML that contains the Pan you seek, that class definition will be passed back to your class loader.
-if you did not specify a package containing the Pan you seek, NoClassDefFoundError will be thrown.
