0

I'm running some code inside JUnit inside IntelliJ and I'm getting an exception

java.lang.LinkageError: ClassCastException: attempting to castjar:file:/C:/zzz/zzz/web/WEB-INF/lib/jakarta.ws.rs-api-2.1.6.jar!/javax/ws/rs/ext/RuntimeDelegate.class to jar:file:/C:/zzz/zzz/web/WEB-INF/lib/jakarta.ws.rs-api-2.1.6.jar!/javax/ws/rs/ext/RuntimeDelegate.class

An the top of the stack trace is:

at javax.ws.rs.ext.RuntimeDelegate.findDelegate(RuntimeDelegate.java:124)
      at javax.ws.rs.ext.RuntimeDelegate.getInstance(RuntimeDelegate.java:96)
      at javax.ws.rs.core.MediaType.toString(MediaType.java:395)
      at com.itf.remote.client.AutoTestingRestClient.doGet(AutoTestingRestClient.java:141)

the code line where it happens:

HttpResponse response = client.doGet(uri, MediaType.APPLICATION_JSON_TYPE.toString());

and it's the toString() method that causes it.

the jar file above is on the classpath only once. What IntelliJ runs is:

C:\Users\loosp\.jdks\temurin-17.0.8\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 
"-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2\lib\idea_rt.jar=34089:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2\bin" -Dfile.encoding=UTF-8 -classpath "
... I removed all jars from here " com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 randstad.junit.ITFTest,Test1

From my investigation so far I understand that the class RuntimeDelegate must have been loaded by 2 different class loaders. But how is that possible? This is happening inside jakarta.ws.rs-api-2.1.6.jar so I'm pretty sure I can trust that.

Any ideas welcome.

I already decompiled the code that this is happening in and it's this method:

private static RuntimeDelegate findDelegate() {
        try {
            Object delegate = FactoryFinder.find("javax.ws.rs.ext.RuntimeDelegate", "org.glassfish.jersey.internal.RuntimeDelegateImpl", RuntimeDelegate.class);
            if (!(delegate instanceof RuntimeDelegate)) {
                Class pClass = RuntimeDelegate.class;
                String classnameAsResource = pClass.getName().replace('.', '/') + ".class";
                ClassLoader loader = pClass.getClassLoader();
                if (loader == null) {
                    loader = ClassLoader.getSystemClassLoader();
                }

                URL targetTypeURL = loader.getResource(classnameAsResource);
                throw new LinkageError("ClassCastException: attempting to cast" + delegate.getClass().getClassLoader().getResource(classnameAsResource) + " to " + targetTypeURL);
            } else {
                return (RuntimeDelegate)delegate;
            }
        } catch (Exception var5) {
            throw new RuntimeException(var5);
        }
    }

But still no idea how can this happen?

  • Is this some kind web application that contains both an EJB container (jar file) and a web container(war file) - possibly both packed into an ear? If that is the case and you messed up building your project and put the RuntimeDelegate.class into both the jar and war file this classcastexceptions tend to happen, because each container has its own classloader afaik. – OH GOD SPIDERS Aug 01 '23 at 17:18
  • `2 different class loaders. But how is that possible?` This is normal in a web application. In short, imagine your web app uses a library, and that library uses some static fields to hold the information it needs to work. Now imagine that another web app in the same container uses the same library. Obviously, the static fields holding information would conflict, causing errors. So web apps use class loaders to partition applications into separate spaces so each can have its own copy of any class, preventing problems. – markspace Aug 01 '23 at 17:19
  • More on class loading: https://stackoverflow.com/questions/18210389/java-ee-and-java-se-classloading – markspace Aug 01 '23 at 17:21
  • Some info on configuring a class loader in a JEE app: https://www.ibm.com/docs/en/was/8.5.5?topic=loading-configuring-application-class-loaders Basically I Googled for "java classloadeer war j2ee jee" and got a ton of hits. It's a well documented process and there's lots of help available. – markspace Aug 01 '23 at 17:24
  • This is not web app. It does make a rest call but this is the client end, pretty simple java. There is no ear, there is no war. This is what makes me wonder. So I'm basically running a standalone java JUnit call which in turn calls my jar that makes a rest call. That is the strangest thing, no Tomcat – Alek Jachowicz Aug 01 '23 at 19:05
  • OK, greate. Question closed and proposed answers isn't even close to what I was asking. To code still doesn't work. Bummer. Comments are valuable but it seems people only read title and didn't get in to details. – Alek Jachowicz Aug 02 '23 at 21:18
  • With all respect @markspace, all you comments assume it's JEE app and it's not. that is the trick in the question. I could google "java classloader war" myself. – Alek Jachowicz Aug 02 '23 at 21:22

0 Answers0