Camunda: cannot be cast to (same class) - java

I've included a .jar in my maven project writing this in pom.xml:
<dependencies>
<dependency>
<groupId>org.loopingdoge.acme.model</groupId>
<artifactId>acme-model</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${basedir}/src/main/webapp/WEB-INF/lib/acme-model.jar</systemPath>
</dependency>
</dependencies>
acme-model.jar contains org.loopingdoge.acme.model.House but this cast
public class HouseAdder implements JavaDelegate {
public void execute(DelegateExecution delegateExecution) throws Exception {
House house = (House) delegateExecution.getVariable("house");
}
}
gives me this error when deployed on a Wildfly server:
18:50:20,255 ERROR [org.camunda.bpm.engine.context] (default task-45) ENGINE-16004 Exception while closing command context:
org.loopingdoge.acme.model.House cannot be cast to org.loopingdoge.acme.model.House: java.lang.ClassCastException: org.loopingdoge.acme.model.House cannot be cast to org.loopingdoge.acme.model.House
at org.loopingdoge.acme.services.HouseAdder.execute(HouseAdder.java:13)

Such cases happens when a class will be loaded over different classloaders. java make them distinct even if package and classname are identical.
You need to find out on which ways this class will be loaded. As first step, find the jars which contains that class.
or/and read this on SO

Ran into the same problem. Further analysis showed that two different class loaders were used, as stated in this thread already. In my case the culprit was devtools of spring boot, a tool which likely many will have active in their pom. Seems that devtools doesn't play well with (in my case) camunda java delegates with embedded camunda engine.

I guess that you have the class in multiple places, e.g. packaged the jar within WildFly and the WAR you deploy. Check that you have the class only one time on the classpath.
By the way: Better not use system dependencies if not absolutely necessary. This is what maven repositories are for.

Related

Upgrading gwt from 2.1.1 to 2.8.0: ServiceConfigurationError: org.apache.juli.logging.Log: Provider org.eclipse.jetty.apache.jsp.JuliLog not a subtype

After upgrading gwt from version 2.1.1 to 2.8.0, I got the error message
2017-04-20 12:59:19.551:WARN:oejuc.AbstractLifeCycle:main: FAILED c.g.g.d.s.j.WebAppContextWithReload#341fbaf1{/,file:/C:/Users/xxx/.IntelliJIdea2017.1/system/gwt/xxx.97baa614/xxx.fdf824a8/run/www/,STARTING}{C:\Users\xxx\.IntelliJIdea2017.1\system\gwt\xxx.97baa614\xx.fdf824a8\run\www}: java.util.ServiceConfigurationError: org.apache.juli.logging.Log: Provider org.eclipse.jetty.apache.jsp.JuliLog not a subtype
java.util.ServiceConfigurationError: org.apache.juli.logging.Log: Provider org.eclipse.jetty.apache.jsp.JuliLog not a subtype
I found some other posts with similar messages, like this or this, but the situation seems to be different:
I do not use Maven or Ant, just pure IntelliJ, I have no reference to any Tomcat library, and I am not aware of any JSP in our application.
I found through debugging that first the class loader com.google.gwt.dev.shell.jetty.Jettylauncher$WebAppContextWithReload$WebAppClassLoaderExtension loads class org.eclipse.jetty.apache.jsp.JuliLog including interface org.apache.juli.logging.Log.
Then, later interface org.apache.juli.logging.Log is loaded by sun.misc.Launcher$AppClassLoader triggered indirectly by
org.eclipse.jetty.webapp.WebAppContext.startContext()
which calls method initialize of an
org.eclipse.jetty.jsp.JettyJspServlet
instance.
I have no idea why a JspServlet needs to be initialized at all, as no JSPs are used in the application, as far as I see, just a few Servlets. And it seems all the classes involved in this conflict are contained in the single jar gwt-dev.jar, so I see no possibility to influence any class loading behavior via class path settings.
Any idea how I could resolve this?
I also got this error upgrading from gwt from version 2.4 to 2.8.2.
Jake W's answer helped me.
To solve this, I ran a maven dependency tree on my project to figure out what was referencing jetty's apache-jsp.
To run the dependency tree, in Eclipse I created a new run configuration -> maven build -> with the goals "dependency:tree -Doutput=/dependency/file.txt". Once it's run, the console output will show where it saves the output. It should be the same location that you referenced with the -Doutput option.
Look for something like this in the output file:
- org.eclipse.jetty:apache-jsp:jar:9.2.14.v20151106:compile
And then look up in the tree to see where it's being pulled in from. In my case it came from this:
+- com.google.gwt:gwt-dev:jar:2.8.2:compile
+- net.sourceforge.htmlunit:htmlunit:jar:2.19:compile
\- org.eclipse.jetty:apache-jsp:jar:9.2.14.v20151106:compile
Once you know where it's coming from, (assuming you're using maven) you can add an exclusion in your pom.xml file for it:
</dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<version>${gwt.version}</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
This worked for me. Thanks :)
I saw this error when I recently upgraded to GWT 2.8.0. Please try to exclude jetty-apache-Jsp related dependencies from your project.
You may see other jetty related issues as well, so please also make sure you are using exactly the same jetty version as GWT 2.8.0 is using.
I'm on mobile at the moment, unable to add more details, but I hope that can be a useful direction to go. Please add your comments if you still see issues, I will then have a look and update the answer when I'm on my laptop.
I have just ran into this exception after adding gwt-test-utils:0.53 dependency (with GWT 2.8.1)
I am using ant and all information found regarding this error indicated there was 2 versions of Juli Logging in the classpath, but every search came up with only gwt-dev.jar. Production builds worked fine, but dev mode did not which needs gwt-dev.jar.
Part of the build process has the jars copied from a local lib directory to war/WEB-INF/lib to pack into the war. The ant script points to the local lib directory for debugging, not the ones meant for the war file. Despite the war location not being listed in the ant file as a class path, it was still loading it.
Ultimately, gwt-dev.jar was conflicting with the copied version of itself.

Replace provided Maven dependency with local class

If I check my effective pom I will find the following entry:
<dependency>
<groupId>com.package.of.other.department</groupId>
<artifactId>someArtifact</artifactId>
<version>2.4.2</version>
<scope>provided</scope>
</dependency>
This comes from the parent pom that we have to use to let our software (bpmn processes) run on a company wide platform.
Now comes a hacky part. There will be a bigger change and we cannot use someArtifact anymore. Unfortunately that artifact gets called directly by all our processes (you design the process and configure the full qualified class name for an item) and can't just configure a different artifact, as that would most likely break a lot of the running processes.
The simple plan was to create a class with the same package name and with the same class name, remove every dependency to the original package and everything should work fine. During the tests I noticed that it doesn't use my new class but still the original one, most likely because it gets provided as dependency via the mandatory parent pom and for some reason prefers that over my local one.
Excluding a provided dependency from the parent pom doesn't seem to work that easily?! Any idea how I could solve my issue?
If the application is regular java, the class that will be load is the first class met in the classpath order.
If you use other runtime package dependency management, the strategy is different. As example you can adjust your import-package in OSGi to ensure the use a class contains in private-package.

About exist two same name class in different jar?

In my current project I used Guava Cache to cache something with expiration, but when actually call this interface, it had below error
Caused by: java.lang.NoSuchMethodError: com.google.common.base.Platform.systemNanoTime()J
at com.google.common.base.Ticker$1.read(Ticker.java:64)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2225)
And the reason is that there are two Platform in the classpath
one in Gauva, one in google-collections:jar
And LocalCache of Guava uses Paltform of google-collections causes this error. I have some question about this, why not Class in the same jar has higher priority? why not randomly choose one, but always use Platform of google-collections?
Yes it is possible that two jars include the same class name. It happens when you import for example two jars of different versions of the same library.
If you import dependencies using maven for example when you import a library it can import dependencies of other libraries causing this kind of problem. In this case you need to explicit that when you import a library you need to exclude a secondary dependency. This is done with the exclusions tag.
You can force priority by specifying classpath order. Java look for class in jars in order that is pecifyed in classpath.
In case you using maven and ide to run you have no control over order of classpath, but you can exclude dependee module from classpath.
<dependency>
<groupId>some</groupId>
<artifactId>id1</artifactId>
<version>1.0.0.0</version>
<exclusions>
<exclusion>
<groupId>another</groupId>
<artifactId>id2</artifactId>
</exclusion>
</exclusions>
</dependency>
In this case id2 will not be in your classpath anymore.
class loading priority will depends on the ClassLoader, you can find lot of articles about java class loading. if you are trying to run a standalone java application probably class loading will be done by URLClassLoader.
in this case all urls(jar file locations or classes) given in the -cp or -classpath will be added as URLs to the URLClassLoader, then when application needs to load a class this URLClassLoader will iterate through its URLs and once it found the class it will be loaded.
so everything depends on the class path order.
NOTE: but in some context class loading is not simple as this. ex: jboss-module class loader.

How do I determine which version of a class my object is?

I'm trying to write a plugin into a framework application (Joget). My plugin source looks something like this:
public class MyPlugin extends ExtDefaultPlugin implements ApplicationPlugin, ParticipantPlugin {
...
public void execute(){
...
SecurityContextImpl secContext = (SecurityContextImpl) WorkflowUtil.getHttpServletRequest().getSession().getAttribute("SPRING_SECURITY_CONTEXT");
}
}
When I run the plugin, I get the following exception.
java.lang.ClassCastException: org.springframework.security.context.SecurityContextImpl cannot be cast to org.springframework.security.context.SecurityContextImpl
I'm using Maven. Now since both have the same package name, I'm assuming I'm accidentally using the wrong package version in my plugin JAR (that contains the SecurityContextImpl class) than the one in the framework. But I've double-checked and it looks like I'm including the correct one in my plugin package.
Is there a way to see the classloader or source JAR of my class (e.g. using reflection in some manner)? Any other ideas on how to address this?
This type of java.lang.ClassCastException, where both classes names are equals, occur when the same class, or two class with the same name are loaded by 2 different classloaders.
I don't know Joget, but you are talking about plugin. Frameworks often load plugins in separate classloaders to ensure a proper isolation between them.
Since you say I've double-checked and it looks like I'm including the correct one in my plugin package., you may want to remove spring-security from your package, as it's probably already loaded by the framework classloader.
You're using Maven, so you may simply add <scope>provided</scope> to the spring-security dependency (but not sure, since we don't have your pom.xml)
I've got the same exception when I was running my plugin.
There are two cases in general:
1. The class is a local class.
And that is to say, there is no repository(groupId, artificateId, etc) to be deployed in the pom.xml of your plugin. The solution is, go the target folder and open the xxx-0.0.1-snapshot.jar file, then open META-INF/MANIFEST.MF, add the source file of that class /dependency/file.jar, then add the source jar to the dependency folder
Remarks: It is better to give a version of the your local file and add it as shown in your pom.xml to let it be found as src in your code.
<!-- your source jar need to be renamed as example-1.0.0.jar -->
<dependency>
<groupId>this.should.be.the.prefix.of.your.package</groupID>
<artificateId>file.name<artificateId>
<version>1.0.0</version>
<systemPath>${basedir}/lib/stclient_updated-1.0.0.jar</systemPath>
<scope>system</scope>
</dependency>
2. The class is a remote class with repository
I had this type of problem once because the repository is not correct, see also Maven Repository to find the official repository of the source.
I hope that it could help =)
Cheers

How to manage dependency on servlet-api?

We have a web maven module that is compiled to a war, and thus doesn't need to include the servlet-api jar directly. We use <scope>provided</scope> for this.
The problem arises when I try to write a small main() to test one of my classes. This is not a unit test, but rather resides with the code itself.
This fails on java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest:
public static void main(String[] args) {
final Injector injector = Guice.createInjector(new StandardModule());
// StandardModule is our standard module, with bindings to
// something that rightfully depends on servlet API
...
}
Besides splitting my module to two or three different modules, is there an easy workaround I haven't thought of?
Perhaps the best solution is to move this tester to the test code.
You can use <scope>test</scope> if you want to have it for tests. However provided works fine for me in Eclipse - it is added to the classpath.
If you use eclipse with m2eclipse, <scope>provided</scope> will be resolved correctly and your main class will compile and run properly.

Categories

Resources