| <html> |
| <head> |
| <title>Using JAM to ease the transition to JSR175</title> |
| |
| <link href="jam.css" rel="stylesheet" type="text/css" /> |
| |
| |
| </style> |
| </head> |
| |
| |
| <body> |
| |
| <h2>Using JAM to ease the transition to JSR175</h2> |
| |
| <p>This document describes how <a href='/stuff/jamdocs'>JAM</a> can help you transition your metadata processing from javadoc tags to <a href='http://www.jcp.org/en/jsr/detail?id=175'>JSR175</a>. |
| |
| |
| |
| |
| <h3>Before you can require 1.5</h3> |
| |
| <p>First, define a set of java beans that reflect what you expect your |
| 175 annotation types to ultimately look like. Ideally, they should also |
| directly reflect the javadoc tags you are currently using. (If they can't, |
| you will have to do a little more work than this example describes - more |
| on that later). Here is a simple example of such a bean:</p> |
| |
| <pre> |
| package foo.bar; |
| |
| /** |
| * This is a 'fake' 175 annotation type that will work under 1.4. |
| * It's just a generic java bean except that it should conform to |
| * the 175 annotation conventions. This means, among other things, |
| * that the getters are not prefixed with 'get'. |
| */ |
| public class MyAnnotation { |
| public MyAnnotation() {} // a public no-arg constructor is required |
| public int id() { return mId;} |
| public void setId(int id) { mId = id; } |
| private int mId = 13; |
| } |
| </pre> |
| |
| <p>In your client/tool code, when creating a JService, you need to specify |
| a mapping between javadoc tag names and the qualified classnames of these |
| annotation beans. For example:</p> |
| |
| <pre> |
| String[][] mappings = { "myannotation", "foo.bar.MyAnnotation" }; |
| JServiceFactory factory = JServiceFactory.getInstance(); |
| JServiceParams params = factory.createServiceParams(); |
| p.setJavadoc175Mappings(mappings); |
| // (also do other stuff like include your .java files in the params) |
| JService service = factory.createService(params); |
| </pre> |
| |
| <p>For every javadoc tag encountered named 'myannotation,' and instance |
| of foo.bar.MyAnnotation will be created and populated by mapping the |
| tag attributes to the setters via reflection. For example, if you |
| were using the JService created above to inspect the following source |
| file: |
| |
| <pre> |
| |
| package foo.bar; |
| |
| /** |
| * @myannotation id=42 |
| */ |
| public class SomeClass { |
| } |
| </pre> |
| |
| <p>you could access the myannotation metadata as follows:</p> |
| |
| <pre> |
| |
| JClass someClass = service.getClassLoader().load("foo.bar.SomeClass"); |
| JAnnotation jAnn = someClass.getAnnotation(MyAnnotation.class); |
| MyAnnotation myAnnotation = (MyAnnotation)jAnn.getAnnotationObject(); |
| System.out.println(myAnnotation.getId()); // prints out 42 |
| |
| </pre> |
| |
| <p>In this way, our access to the javadoc'ed metadata is strongly-typed, |
| structured, and isolated from the vagaries of javadoc parsing. Better still, |
| the stage is now set for an easy transition to JSR175-style annotations, |
| even though none of the code here requires JDK 1.5.</p> |
| |
| |
| <h3>After you can require 1.5</h3> |
| |
| <p>Once you are sure that you can require JRE 1.5, and |
| that you no longer need to support javadoc tags, the transition away from |
| this mechanism is extremely simple. Building on the previous example, |
| the first step is to change MyAnnotation.java so that MyAnnotation is a |
| genuine 175 annotation:</p> |
| |
| <pre> |
| package foo.bar; |
| |
| /** |
| * This is a genuine 175 annotation type. |
| */ |
| public @interface MyAnnotation { |
| int id() default 13; |
| } |
| </pre> |
| |
| <p>It is important to be sure that the package and class name remains the |
| same so that your client code does not need to change. With this done, |
| it no longer is necessary to provide the javadoc-to-class mappings |
| as we did above when creating the JService. Now, all we have to do is:</p> |
| |
| <pre> |
| JServiceFactory factory = JServiceFactory.getInstance(); |
| JServiceParams params = factory.createServiceParams(); |
| // (also do other stuff like include your .java files in the params) |
| JService service = factory.createService(params); |
| </pre> |
| |
| <p>That's it. The beautiful part is that our client code does not |
| have to change at all:</p> |
| |
| <pre> |
| JClass someClass = service.getClassLoader().load("foo.bar.SomeClass"); |
| JAnnotation jAnn = someClass.getAnnotation(MyAnnotation.class); |
| MyAnnotation myAnnotation = (MyAnnotation)jAnn.getAnnotationObject(); |
| System.out.println(myAnnotation.getId()); // still prints out 42 |
| </pre> |
| |
| <p>The MyAnnotation instance we get here is no longer the annnotation |
| bean we defined earlier - it's a real java.lang.annotation.Annotation. |
| But the beauty of it is that because we planned things out well, it |
| doesn't make any difference to the client code.</p> |
| |
| <p>Again, though, it's important to note that once we get to this point, |
| nothing will work without JRE 1.5, and javadoc-style metadata will no |
| longer be recognized.</p> |
| |
| </body> |
| </html> |