I think most of my projects are driven by anger/rage, and this one is no exception. I was doing a hobby project, and I had to write a META-INF/services/Something file and put a fully-qualified name of my class that implements Something.

Now, I've done this countless times, and while I hated every time, I sort of looked the other way and just wrote it manually. But tonight, I guess it was just one too many. I felt that my human dignity is at stake here ? we shouldn't be doing what machines can do!

So I wrote a little annotation processor, by using JSR-269, that generates META-INF/services for me. And here's how to use it.

On classes that you'd like listed as service providers, put @MetaInfServices annotation. As long as you only have one interface or one super class, that type is assumed to be the contract. So given the example below:

import org.kohsuke.MetaInfServices

@MetaInfServices
public class MyProvider implements SomeContract {
  ...
}

You get the META-INF/services/com.example.SomeContract file whose content is org.acme.MyProvider.

If you have multiple interfaces and/or base type, the library cannot infer the contract type. In such a case, specify the contract type explicitly by giving it to @MetaInfServices like this:

import org.kohsuke.MetaInfServices

@MetaInfServices(ContractType.class)
public class MyProvider extends AbstractSet implements Comparable, Serializable, Closeable {
  ...
}

When you use javac in JavaSE6, META-INF/services/* files are generated automatically. No additional compiler switches are necessary. This library also handles incremental compilation correctly, too, so it works nicely from inside Ant or Maven.

If you are using Maven for your build tool, you should specify metainf-services.jar as an optional dependency to avoid having the jar in the runtime. This will save 6KB in the runtime footprint.


<dependency>
&#160; <groupId>org.kohsuke.metainf-services</groupId>
&#160; <artifactId>metainf-services</artifactId>
&#160; <version>1.1</version>
&#160; <optional>true</optional>
</dependency>

The artifact is deployed in the java.net Maven2 repository, but because org.kohsuke has an auto-sync set up to the Maven central repository, the jar should be available on the central repository in a day or two.

Why this is not a part of JavaSE6 itself is beyond me, but at least now I can go back to my real hobby project that I was working on, before getting side-tracked by this hobby project.

P.S. I saw some people uses acronyms like "NOTD" (news of the day), "TOTD" (tip of the day), so I think I'll follow the convention and call this "POTD" which stands for "project of the day."