0

createController on line 29 in the below stack trace has clazz.getClasslo

protected Object createController(Injector injector, String controllerClassFullName) {
    Class<?> clazz = classLoader.clazzForName(controllerClassFullName);
    return injector.getInstance(clazz); //line 29!!!!
}

loadClass online 521 is loading a class of the constructor of the above 'clazz' variable BUT is not loading from CompilingClassLoader. It somehow is skipping it. There are THREE parameters to the constructor all loading from CompilingClassLoader except the last one :(

Here is the constructor I am talking about(you can see it calling getDeclaredConstructors in the stack trace)

@Inject
public CustomerController(
        HashCreator hashCreator,
        TokenGenerator tokenGenerator,
        DataClientProxy clientProxy
) {
    this.hashCreator = hashCreator;
    this.tokenGenerator = tokenGenerator;
    this.clientProxy = clientProxy;
}

Finally here is the stack trace

loadClass:521, ClassLoader (java.lang)
getDeclaredConstructors0:-1, Class (java.lang)
privateGetDeclaredConstructors:3137, Class (java.lang)
getDeclaredConstructors:2357, Class (java.lang)
forConstructorOf:245, InjectionPoint (com.google.inject.spi)
create:115, ConstructorBindingImpl (com.google.inject.internal)
createUninitializedBinding:706, InjectorImpl (com.google.inject.internal)
createJustInTimeBinding:930, InjectorImpl (com.google.inject.internal)
createJustInTimeBindingRecursive:852, InjectorImpl (com.google.inject.internal)
getJustInTimeBinding:291, InjectorImpl (com.google.inject.internal)
getBindingOrThrow:222, InjectorImpl (com.google.inject.internal)
getProviderOrThrow:1040, InjectorImpl (com.google.inject.internal)
getProvider:1071, InjectorImpl (com.google.inject.internal)
getProvider:1034, InjectorImpl (com.google.inject.internal)
getInstance:1086, InjectorImpl (com.google.inject.internal)
createController:29, DevLoader (org.webpieces.devrouter.impl)

How in the world are the first two parameters loaded from CompilingClassLoader and the 3rd constructor is loaded from a normal ClassLoader. I thought any children classes should go through the same classloader as the parent to load?

(I am trying to fix this as for some reason, the CompilingClassLoader is missing loading that class causing a very fun like existence of TWO DataApi.class objects loaded by different classloaders).

Hmmm, As I dig more, I found out I can call clazz.getMethods() BUT when I call clazz.getDeclaredConstructors(), then I get a ClassCircularityError. The real funny thing is CustomerController nor DataClientProxy extend anyone so it's really weird.

Dean

Dean Hiller
  • 19,235
  • 25
  • 129
  • 212
  • The container probably has its own classloader, and container injection falls somewhere on the spectrum of magic, so it can do what it likes, however... why do you care? The only difference that comes to mind with 2 loaders is `dataApiObj1.getClass().equals(dataApiObj2.getClass())` but `dataApiObj1.getClass() != dataApiObj2.getClass()` – Bohemian May 28 '20 at 21:59

1 Answers1

0

Nastiness. So, the file had the wrong package name. While eclipse doesn't allow this and intellij flags it as red, gradle and java let it compile just fine but when we look for source, we can't find the source so it ends up we can't load it via the CompilingClassLoader causing a very confusing issue. I can't even throw an exception to this effect telling the developer the package is wrong because I only receve classnames and have no idea if the package name is wrong or not since all classes go through this classloader. ick.

Dean Hiller
  • 19,235
  • 25
  • 129
  • 212