Issue
I'm facing this issue for the first time, here's the exception that gets thrown in the service
Exception in thread "Thread-1" java.lang.NoSuchMethodError: org.codehaus.jackson.type.JavaType.<init>(Ljava/lang/Class;)V
at org.codehaus.jackson.map.type.TypeBase.<init>(TypeBase.java:13)
at org.codehaus.jackson.map.type.SimpleType.<init>(SimpleType.java:45)
at org.codehaus.jackson.map.type.SimpleType.<init>(SimpleType.java:40)
at org.codehaus.jackson.map.type.TypeFactory._fromClass(TypeFactory.java:374)
at org.codehaus.jackson.map.type.TypeFactory._fromType(TypeFactory.java:434)
at org.codehaus.jackson.map.type.TypeFactory.type(TypeFactory.java:61)
at org.codehaus.jackson.map.ObjectMapper.<clinit>(ObjectMapper.java:174)
at com.kx.proto.validation.util.Common.<clinit>(Common.java:41)
and once this exception is thrown, the service stops receiving the subsequent api calls made to the service ( even though i have caught the exception ) , pod is still in running state. I'm curious about two things here
- The exception that gets thrown, how to fix that ? Change in POM file?
- Why would the exception that has been caught would stop service from receiving further REST api calls. Basically after the exception , all the apis in service start timing out.
Below is the piece of code where exception gets thrown
at this line
GeneratedMessageV3 messageV3 = Common.loadDefaultObjectFromMessage("com.kx.proto.", recordId.toUpperCase() + "Record");
and here's the loadDefaultObject from message method
public static GeneratedMessageV3 loadDefaultObjectFromMessage(String pkg, String messageName) {
try {
Class<?> record = Class.forName(pkg + messageName);
Optional<Method> getDefaultInstance = Arrays.asList(record.getDeclaredMethods()).stream().filter((method) -> {
return method.getName().equals("getDefaultInstance");
}).findFirst();
if (getDefaultInstance.isPresent()) {
Object obj = ((Method)getDefaultInstance.get()).invoke((Object)null, (Object[])null);
return (GeneratedMessageV3)obj;
}
} catch (ClassNotFoundException var5) {
System.out.println("class not found " + var5.getMessage());
} catch (Exception var6) {
var6.printStackTrace();
}
return null;
}
Solution
NoSuchMethodError is an Error (not an Exception) that occurs when the classpath during compilation differs from the classpath at runtime.
It says: I could find that method during compilation, but I can't find that method now at runtime.
It typically occurs when the runtime classpath differs from the compilation classpath. This gets more complex if your project A depends on jar B which depends on jar C. Presume all three projects (A, B and C) are compiled/released at a different time.
Start with doing mvn dependency:tree
on your project. Ask the verbose version of that. One typical cause is dependency versions overrides with a lower version. For example your project A depends on C 1.2 and B 3.0 but B 3.0 depends on C 1.4. What if B was compiled using a method of C that only exists since C 1.3? When B is run in project A with C 1.2 instead of C 1.4, it doesn't find that method and NoSuchMethodError is thrown.
Note: there is an enforcer rule to enforce not downgrading transitive dependencies. It's very useful to avoid such surprises at runtime.
Answered By - Geoffrey De Smet
Answer Checked By - Terry (JavaFixing Volunteer)