title: Parent-Child Classloader Class Resolution
body: <h2>The tasks and initial investigation</h2>
  
  <p>I try to set up two Oracle Coherence near cache instances at one java swing application. The idea a solution could be found <a href="http://codefhtagn.blogspot.co.uk/2011/05/joining-multiple-coherence-clusters.html" rel="nofollow">here</a>. My case is a bit more complicated and this is where the game starts. </p>
  
  <h2>Short description</h2>
  
  <p>In my case there is an <em>account service</em>. It can have two endpoints: SIT and UAT. In order to create two such services, I need to load two 'instances' of the Coherence in order to override the endpoints with system variables (<em>tangosol.coherence.cacheconfig</em>). </p>
  
  <p>I have: </p>
  
  <ul>
  <li>the main code of the app is located in the mainapp.jar; </li>
  <li>the <em>AccountService</em> interface that is located in the account-interfaces.jar; </li>
  <li>the <em>AccountServiceImpl</em> class that is located in the account-impl.jar and implements the <em>AccountService</em> interface; </li>
  <li>my main application has the following structure
  
  <blockquote>
  <pre><code>bin: startup.bat, startup.sh
  conf: app.properties
  lib: mainapp.jar, account-interfaces.jar, account-impl.jar, coherence.jar
  </code></pre>
  </blockquote></li>
  </ul>
  
  <h2>Approach tried</h2>
  
  <p>I created a dedicated child-first classLoader - InverseClassLoader and made the AppLaunchClassLoader (the default Thread.currentThread().GetContextClassLoader() classLoader) it's parent. With the InverseClassLoader I load the AccountServiceImpl class:</p>
  
  <pre><code>Class&lt;AccountServiceImpl&gt; acImplClass = contextClassLoader.selfLoad(AccountServiceImpl.class).loadClass(AccountServiceImpl.class);
  Constructor&lt;AccountServiceImpl&gt; acConstructor =
  acImplClass .getConstructor(String.class); 
  AccountService acService = acConstructor .newInstance(serviceURL);
  </code></pre>
  
  <h2>Issues and questions</h2>
  
  <ol>
  <li>I get the 'AccountServiceImpl cannot be cast to AccountService' exceptions, which means that those two classes loaded by different classloaders. <strong>But</strong> those classloaders are in the parent-child relationship. So am I right that even if a class is loaded by a parent (interface - 'abstract' type) it can't be used with a class (concrete impl) loaded by a child classloader? Why then we need this parent-child relation?</li>
  <li>I specified the AccountService interface in a code and it got loaded by a default classloader. I tried wrap the code above is a thread and set the InverseClassLoader it's context classloader. Nothing changed. So am I right that I can't use such interface-implementation coding (as usual coding) and need to use reflection all the time to invoke concrete methods all the time? (Hope there is a solution)  ;</li>
  <li>Say, I listed both the AccountService and AccountServiceImpl classes for being loaded by the InverseClassLoader. What if I need other classes, that are accessible by those two, to be also loaded by the InverseClassLoader? It there a way to say that all 'related' classes must be loaded by the same classloader?</li>
  </ol>
  
  <h2>Update</h2>
  
  <p>Here is the InverseClassLoader:</p>
  
  <pre><code>public class InvertedClassLoader extends URLClassLoader {
  
  private final Set&lt;String&gt; classesToNotDelegate = new HashSet&lt;&gt;();
  
  public InvertedClassLoader(URL... urls) {
      super(urls, Thread.currentThread().getContextClassLoader());
  }
  
  public InvertedClassLoader selfLoad(Class&lt;?&gt; classToNotDelegate) {
      classesToNotDelegate.add(classToNotDelegate.getName());
      return this;
  }
  
  @Override
  public Class&lt;?&gt; loadClass(String className, boolean resolve) throws ClassNotFoundException {
      if (shouldNotDelegate(className)) {
          System.out.println("CHILD LOADER: " + className);
          Class&lt;?&gt; clazz = findClass(className);
          if (resolve) {
              resolveClass(clazz);
          }
          return clazz;
      }
      else {
          System.out.println("PARENT LOADER: " + className);
          return super.loadClass(className, resolve);
      }
  }
  
  public &lt;T&gt; Class&lt;T&gt; loadClass(Class&lt;? extends T&gt; classToLoad) throws ClassNotFoundException {
      final Class&lt;?&gt; clazz = loadClass(classToLoad.getName());
      @SuppressWarnings("unchecked")
      final Class&lt;T&gt; castedClass = (Class&lt;T&gt;) clazz;
      return castedClass;
  }
  
  private boolean shouldNotDelegate(String className) {
      if (classesToNotDelegate.contains(className) || className.contains("tangosol") ) {
          return true;
      }
      return false;
  }
  </code></pre>