title: Using `META-INF/services` for internal plumbing of driver
body: <p>I develop the Jaybird JDBC driver, and today I came across an issue (<a href="http://tracker.firebirdsql.org/browse/JDBC-325" rel="nofollow noreferrer">JDBC-325</a>, <a href="https://stackoverflow.com/questions/18904451/how-to-configure-jaybird-with-hibernate">How to configure Jaybird with hibernate</a>) that is related to how Jaybird loads some of its components and how - in this case - NetBeans restricts classloading.</p>
  
  <p>The issue is related to the way Jaybird loads parts of itself using entries in <code>META-INF/services</code> and the that a classloader used by NetBeans for a Hibernate wizard explicitly ignores those files (see details below).</p>
  
  <p>I can workaround this issue by (also) attempting to load a hardcoded list of plugins that are part of the Jaybird implementation, or by moving the definition to a different location.</p>
  
  <p>However I was wondering if it is weird (or wrong) to use <code>META-INF/services</code> for internal purposes like Jaybird does?</p>
  
  <p>I also don't understand why would NetBeans would exclude loading of <code>META-INF/services</code>? The comment by <em>Drew</em> seems to indicate NetBeans used it to solve errors when loading a driver (see <a href="https://netbeans.org/bugzilla/show_bug.cgi?id=194915" rel="nofollow noreferrer">this issue</a>), although I would think that would be better solved by the user including all dependencies of a driver.</p>
  
  <h2>Details of the problem</h2>
  
  <p>Jaybird uses plugins for the supported protocols, for example the Type 4 protocol, a custom Type 4 Open Office protocol, the Type 2 embedded (native) protocol and the Type 2 native client protocol. I also believe a third party once used it to provide a driver that translated Oracle specific syntax to Firebird syntax. </p>
  
  <p>All these plugins are listed in <code>META-INF/services/org.firebirdsql.gds.impl.GDSFactoryPlugin</code> and are loaded in a way that is similar to <a href="http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html" rel="nofollow noreferrer"><code>java.util.ServiceLoader</code></a> (current 2.2.x drivers still support Java 5 so we don't actually use <code>ServiceLoader</code>). For the upcoming version I was also planning to use this for the supported connection encodings and (wire) protocol definitions. This would allow for 'custom' encoding definitions (eg extend the supported encodings, or use an alternate encoding) or different protocol implementation (eg for troubleshooting, custom logging etc).</p>
  
  <p>Now the actual problem is that the Netbeans wizard <em>Hibernate Mapping Files and POJOs from Database</em> uses a custom classloader (<code>org.netbeans.modules.hibernate.util.CustomClassLoader</code>), and this classloader ignores files in <code>META-INF/services</code>. Note that it is only this Wizard that has issues, Netbeans itself can use the driver without problems.</p>
  
  <p>Code ignoring <code>META-INF/services</code>:</p>
  
  <pre><code>@Override
  public URL findResource(String name) {
      return name.startsWith("META-INF/services") ? null : super.findResource(name); //NOI18N
  }
  
  @Override
  public Enumeration&lt;URL&gt; findResources(String name) throws IOException {
      if (name.startsWith("META-INF/services")) { //NOI18N
          return Collections.enumeration(Collections.&lt;URL&gt;emptyList());
      } else {
          return super.findResources(name);
      }
  }
  </code></pre>
  
  <p>This results in no plugins being discovered and the driver has no protocols, which leads to a <code>NullPointerException</code> inside Netbeans because no connection is created.</p>