4 Replies Latest reply: May 31, 2009 5:01 PM by 843793 RSS

    Service provider discovery for compilation / annotation processing?

    843793
      Hey,

      This is an annoyance that's been in plain sight for years for me but I've miraculously managed to overlook it all the time. My database-glue annotation processor that connects to a database to retrieve meta-data for it's work needs to do a Class.forName on the JDBC driver even though it's jar file has a correct META-INF/services/java.sql.Driver file. This is a bit annoying since then that class name has to be specified in the code using my annotation processor. I take it javac doesn't do discovery of other things than annotation processors, at least not JDBC drivers? If so can my annotation processor kick-start it?

      Thanks
        • 1. Re: Service provider discovery for compilation / annotation processing?
          jschellSomeoneStoleMyAlias
          The jar file, which is the final product of the compilation process has the name in it and you wish the compilation process to use that jar?

          I see a circularity problem there.
          • 2. Re: Service provider discovery for compilation / annotation processing?
            843793
            I guess I wasn't clear, but no, I'm not trying to do anything like that, the things I'm trying to load have nothing to with what is being compiled.

            Basically I'm trying to get:
            DriverManager.getConnection("jdbc:somedatabasetype://somehost/somedb");
            To work in my JSR 269 annotation processor without first doing:
            Class.forName("com.somedatabasetype.Driver");
            Which of course isn't neccesary when running it normally since JDBC 4 service discovery takes care of that. I've now tried doing the discovery and classloading manually, but:
            java.lang.ClassLoader.getSystemResources("META-INF/services/java.sql.Driver")
            And:
            java.util.ServiceLoader.load(java.sql.Driver.class);
            When run during annotation processing don't return the resource files or services of jars given on classpath. So I gather that it's done differently during compilation and annotation processing than under normal conditions, which is understandable, but I'd still like to avoid that the JDBC driver name has to be explicitly specified if possible.
            • 3. Re: Service provider discovery for compilation / annotation processing?
              jschellSomeoneStoleMyAlias
              If you are in fact running DriverManager.getConnection() versus just using it then I doubt that service discovery doesn't work. Unless of course you didn't set it up.

              Conversely if you are not running it then no reason for service discovery to work.
              • 4. Re: Service provider discovery for compilation / annotation processing?
                843793
                The service discovery of drivers in DriverManager indeed does not work under JSR 269 annotation processors without a little fudging, I get a SQLException when it kicks in. But I've figured it out, thanks to this old thread: [http://forums.sun.com/thread.jspa?threadID=5240995].

                From the source I see DriverManager first tries the native getCallerClassLoader() method and falls back to the current thread context class loader, which is, as mentioned in that forum thread, the wrong one to use for this purpose in an annotation processor.

                If I run the following before invoking DriverManager.getConnection():
                for( java.sql.Driver driver : ServiceLoader.load(java.sql.Driver.class, this.getClass().getClassLoader()) ){}
                Then all is well.