Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-context forward results in ClassCastException of TracingLogger #5404

Closed
gluser1357 opened this issue Aug 31, 2023 · 4 comments · Fixed by #5405
Closed

Cross-context forward results in ClassCastException of TracingLogger #5404

gluser1357 opened this issue Aug 31, 2023 · 4 comments · Fixed by #5405

Comments

@gluser1357
Copy link

We observed recently that forwardings from a Jersey filter in webapp A to a resource of another webapp B (requiring <Context crossContext="true"> in context.xml) like...

  ServletContext sc = context.getContext("/webapp");
  RequestDispatcher dispatcher = sc.getRequestDispatcher("/test");
  dispatcher.forward(request, response);

...lead always to the following exception, making forward's effectively impossible:

java.lang.ClassCastException: org.glassfish.jersey.message.internal.TracingLogger$1
cannot be cast to org.glassfish.jersey.message.internal.TracingLogger

We use Jersey 3.1.3 and Tomcat 10.1.

We found this error already described in an article from 2015: https://stackoverflow.com/questions/29558166/cross-context-request-forwarding-in-tomcat-results-in-java-lang-classcastexcepti

How can this error be fixed or avoided?

@jansupol
Copy link
Contributor

This is TracingLogger$1:

class TracingLogger$1 extends TracingLogger
{

            public boolean isLogEnabled(ent event)
            {
/*  84*/        return false;
            }

            public transient void log(ent ent, Object aobj[])
            {
            }

            public transient void logDuration(ent ent, long l, Object aobj[])
            {
            }

            public long timestamp(ent event)
            {
/*  99*/        return -1L;
            }

            public void flush(MultivaluedMap multivaluedmap)
            {
            }

            TracingLogger$1()
            {
            }
}

This ClassCastException is interesting, it looks like if there was a classloading issue with multiple classloaders involved. The SO issue mentions two versions of Jersey, both the same version, but duplicated jars, one jar in one app, second in tomcat.

Is it possibly your case, too?

@gluser1357
Copy link
Author

Ok, see minimal example on https://github.com/gluser1357/jerseyissues/tree/issue-5404-crosscontext.

Could you please test and try to reproduce the problem? Please refer to the readme.txt for short instructions.

To your latest question - Jersey jars are part of both webapps, yes. Since both webapps have identical content, Jersey jars exist twice in Tomcat and are of the same version. Since I started with a clean Tomcat instance I don't think that other Jersey libraries are on the classpath.

@jansupol
Copy link
Contributor

jansupol commented Sep 5, 2023

Each app is loaded by a different instance of ParallelWebappClassLoader. The instance of TracingLogger loaded by jerseyissue-5404 classloader cannot be cast to the TracingLogger loaded by jerseyissue2-5404 classloader. Hence the class cast exception.

As a workaround, try to use a shared library with Jersey in Tomcat, which should be loaded by the parent URLClassLoader and so the class should be castable.

We try to provide a fix to check whether the property is of the TracingLogger class.

@gluser1357
Copy link
Author

Super, thank you. A fix would be great since shared libs have their own issues to take care of.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants