Search |
||
My project of the day: META-INF/services file generatorPosted by kohsuke on March 26, 2009 at 11:41 PM PDT
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.
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." »
Related Topics >>
Java Tools Comments
Comments are listed in date ascending order (oldest first)
Submitted by bnevins on Mon, 2009-05-18 21:40.
Coolio!
Submitted by km on Sun, 2009-04-26 17:50.
KK,
Good stuff. I think you should call it the POTH (Project of the Hour) ;).
Krishna, ntdll results in programmatic frame. Maybe http://weblogs.java.net/blog/kohsuke/archive/2009/02/crash_course_on.html will help you further?
-Kedar
Submitted by musketyr85 on Fri, 2009-03-27 00:41.
Nice and simple. Great job! This should work even nicer with new jsr 308 features in Java 7:
public class MyProvider implements @ MetaInfServices SomeContract {
...
}
You should made proposal to project coin to include this in Java 7 (http://openjdk.java.net/projects/coin/).
Actually, we have JSR 226
Submitted by abbeysen92 on Mon, 2009-09-07 13:04.
Actually, we have JSR 226 working on phoneME Advanced coursework | coursework help | coursework writing for Windows Mobile. But to build it there are some internal dependencies we need to fix - we plan to have it fully buildable in open source soon.
buy coursework | course work | custom coursework
Submitted by francisdb on Fri, 2009-03-27 01:16.
I wrote a plugin for maven that generates the file:
http://jira.codehaus.org/browse/MOJO-1272
Submitted by kohsuke on Fri, 2009-03-27 13:55.
musketyr85 --- Does project coin accept library changes? Because this is not a language change. I should check with Joe Darcy.
francisdb --- If your project somehow cannot require JDK6 for development, or you cannot require JRE5 for runtime environment, then sounds like your solution could be useful.
Submitted by r_spilker on Sat, 2009-03-28 15:39.
You could also have a look at http://spi.googlecode.com That project uses the @ProviderFor annotation. Apart from generating the services file it also does some static analyses to check if the implementation does or one of its supertypes implements or extends the declared service. Furthermore, it will generate errors if the class is not instantiable by the ServiceLoader. One more thing: it work on incremetal builds, which is great for IDE-support.
Submitted by kohsuke on Sat, 2009-03-28 21:18.
Yeah, your library seems to do the exact same thing. Bummer it didn't show up in my Google search. Just to clarify, as I noted in my post, mine does incremental compilation correctly, too.
Submitted by krishna111 on Wed, 2009-04-08 22:08.
hi Kohsuke, i am gettig following issue while accessing com4j.jar at runtime.
sorry as this is not the right place to post, but trying to reach u at the earliest.
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x7c9109f9, pid=5244, tid=1704
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_06-b05 mixed mode)
# Problematic frame:
# C [ntdll.dll+0x109f9]
#
--------------- T H R E A D ---------------
Current thread (0x0aeb8f50): JavaThread "ComThread for main" daemon [_thread_in_native, id=1704]
siginfo: ExceptionCode=0xc0000005, reading address 0x00000010
Registers:
EAX=0x000bca10, EBX=0x00090000, ECX=0x00000010, EDX=0x00003f50
ESP=0x0b49f734, EBP=0x0b49f740, ESI=0x000bca08, EDI=0x000bc9a0
EIP=0x7c9109f9, EFLAGS=0x00010246
Top of Stack: (sp=0x0b49f734)
0x0b49f734: 00090000 000bc9c8 00000000 0b49f814
0x0b49f744: 7c91082c 000901c8 00000010 0b49f7f8
0x0b49f754: 00000000 00000010 77606034 000bc9d0
0x0b49f764: 00000000 0b49f8f4 000c42d4 000901c8
0x0b49f774: 0b49f88c 00000004 00000000 0b49f790
0x0b49f784: 000901c8 00000010 00000018 0b49f858
0x0b49f794: 00000010 00000018 00000006 0aeb8f50
0x0b49f7a4: 00000000 6d6e5e45 00000006 0aeb8f50
Instructions: (pc=0x7c9109f9)
0x7c9109e9: 85 92 00 00 00 8b 4e 0c 8d 46 08 8b 10 89 4d 0c
0x7c9109f9: 8b 09 3b 4a 04 89 55 14 0f 85 2b 0d 00 00 3b c8
Stack: [0x0b460000,0x0b4a0000), sp=0x0b49f734, free space=253k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [ntdll.dll+0x109f9]
C [ntdll.dll+0x1082c]
C [ole32.dll+0x1d01c]
C [OLEAUT32.dll+0x4aa8]
C [OLEAUT32.dll+0x48b5]
request ur kind attention..
--krishna
Submitted by dofcupucbi on Mon, 2009-05-04 17:35.
Cool, I had something similar in mind. I intended empty files placed in META-INF/services to be populated automatically. After reading your post I decided annotations would be a better idea.
But I'd like to type even less, so I'd like to invert the annotation relationship. I'd annotate the service interface and anything implementing it becomes a provider. This would also help with inferring the service types.
|
||
|
|