<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Xebia Blog &#187; annotation</title>
	<atom:link href="http://blog.xebia.com/tag/annotation/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.xebia.com</link>
	<description>Software development done right!</description>
	<lastBuildDate>Wed, 01 Feb 2012 00:30:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>@Composite &#8211; Macro Annotations for Java</title>
		<link>http://blog.xebia.com/2009/06/23/composite-macro-annotations-for-java/</link>
		<comments>http://blog.xebia.com/2009/06/23/composite-macro-annotations-for-java/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 07:22:09 +0000</pubDate>
		<dc:creator>Andrew Phillips</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[annotation]]></category>
		<category><![CDATA[composite]]></category>
		<category><![CDATA[macro]]></category>
		<category><![CDATA[Spring]]></category>

	<!-- AutoMeta Start -->
	<category></category>
	<!-- AutoMeta End -->
	
		<guid isPermaLink="false">http://blog.xebia.com/?p=2156</guid>
		<description><![CDATA[Some months ago I attended a presentation at which Wilfred Springer demonstrated his very cool Preon binary codec library. Defining binary file formats in Preon requires quite a lot of fairly repetitive sets of annotations, and during a chat after the talk Wilfred mentioned (in fact, he blogged about it) how much more convenient it [...]]]></description>
			<content:encoded><![CDATA[<p>Some months ago I attended a presentation at which <a href="http://blog.flotsam.nl/" target="_new">Wilfred Springer</a> demonstrated his very cool <a href="http://preon.sourceforge.net/" target="_new">Preon</a> binary codec library. Defining binary file formats in Preon requires quite a lot of fairly repetitive sets of annotations, and during a chat after the talk Wilfred mentioned (in fact, he <a href="http://agilejava.com/blog/?p=162" target="_new">blogged about it</a>) how much more convenient it would be if one could just define &#8220;shortcuts&#8221;:</p>
<pre lang="java">@RequiredEnumProperty(column = "AGENT")</pre>
<p> for </p>
<pre lang="java">@NotNull
@Column(name = "AGENT")
@Enumerated(EnumType.STRING)
</pre>
<p> for instance &#8211; and use those instead. Sort-of &#8220;macro annotatations&#8221; for Java, if you like.<br />
A thought that has presumably also occurred to many frequent users of Hibernate, JAXB or other annotation-heavy frameworks.</p>
<p>Well, it took me rather longer than the couple of days it would probably have taken a developer of Wilfred&#8217;s skill, but finally <strong>@Composite</strong> is here!<span id="more-2156"></span></p>
<p>Just to dispel any misconceptions up front: here be no bytecode weaving or other runtime magic, so <strong>@Composite</strong> does not affect the semantics of the &#8220;regular&#8221; <a href="http://java.sun.com/javase/6/docs/api/java/lang/reflect/AnnotatedElement.html" target="_new">AnnotatedElement</a> methods<sup>1</sup>. Composite annotations are instead supported via an <a href="http://code.google.com/p/aphillips/source/browse/at-composite/trunk/src/main/java/com/qrmedia/pattern/compositeannotation/api/AnnotatedElements.java" target="_new">AnnotatedElements</a> interface, which provides all the familiar annotation-related methods, and &#8220;unpacks&#8221; registered composite annotations to their &#8220;leaf&#8221; types.<br />
So <strong>@Composite</strong> is not (yet) drop-in magic &#8211; you will need to explicitly call the <tt>AnnotatedElements</tt> interface from your code.</p>
<h3>Hello composite World</h3>
<p>The <a href="http://code.google.com/p/aphillips/source/browse/at-composite/trunk/src/test/java/com/qrmedia/pattern/compositeannotation/example/AtCompositeDemo.java" target="_new">AtCompositeDemo</a> class included in the project basically looks like this:</p>
<pre lang="java">public class AtCompositeDemo {
    ...
    // define a composite annotation
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    @CompositeAnnotation
    public @interface TargetRetentionLeafCompositeAnnotation {
        boolean runtimeRetention() default false;

        @LeafAnnotation
        Target targetLeafAnnotation() default @Target({ ElementType.METHOD });

        @LeafAnnotation(factoryClass = RetentionLeafAnnotationFactory.class)
        Retention retentionLeafAnnotation() default @Retention(RetentionPolicy.RUNTIME);
    }

    // apply the composite annotation...
    @Resource
    @TargetRetentionLeafCompositeAnnotation(runtimeRetention = true)
    private static @interface AnnotatedAnnotation {}

    // ...to two targets
    @Resource
    @TargetRetentionLeafCompositeAnnotation(runtimeRetention = false)
    private static @interface OtherAnnotatedAnnotation {}

    public static void main(String[] args) {
	// get a configured instance of the AnnotatedElements interface
        AnnotatedElements annotatedElements = ...

        log.info("Retrieving annotations from AnnotatedAnnotation.class");
        log.info(Arrays.toString(annotatedElements.getAnnotations(AnnotatedAnnotation.class)));

        log.info("Retrieving annotations from OtherAnnotatedAnnotation.class");
        log.info(Arrays.toString(annotatedElements.getAnnotations(OtherAnnotatedAnnotation.class)));
    }

}
</pre>
<p>When run, it should produce output similar to the following</p>
<pre>Retrieving annotations from AnnotatedAnnotation.class
[@javax.annotation.Resource(shareable=true, mappedName=, description=, name=,
type=class java.lang.Object, authenticationType=CONTAINER), @java.lang.annotation.Retention(
value=RUNTIME), @java.lang.annotation.Target(value=[METHOD])]
Retrieving annotations from OtherAnnotatedAnnotation.class
[@javax.annotation.Resource(shareable=true, mappedName=, description=, name=,
type=class java.lang.Object, authenticationType=CONTAINER), @java.lang.annotation.Retention(
value=CLASS), @java.lang.annotation.Target(value=[METHOD])]
</pre>
<p>which demonstrates the key features of <strong>@Composite</strong>: namely, that the composite annotation is correctly &#8220;expanded&#8221; into a <tt>@Target</tt> and a <tt>@Retention</tt> annotation, and the &#8220;regular&#8221; <tt>@Resource</tt> annotation is still picked up.</p>
<h3>Defining composite annotations</h3>
<p>OK, so let&#8217;s dive into this in a bit more detail. A composite annotation is just a regular <a href="http://www.ibm.com/developerworks/java/library/j-annotate2.html" target="_new">custom annotation</a> which is itself annotated with <tt>@CompositeAnnotation</tt>. Like any other annotation, it may have members, which may be of primitive or annotation type, amongst others. For instance</p>
<pre lang="java">@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@CompositeAnnotation
public @interface DoubleOhAgentCompositeAnnotation {
    ...
}
</pre>
<p>The &#8220;leaf&#8221; annotations &#8211; the annotations that the composite &#8220;expands&#8221; to &#8211; are simply members that are annotated with <tt>@LeafAnnotation</tt>. Of course, this only makes sense if these members <em>return an annotation type</em>! Note that members of a composite annotation are not <u>automatically</u> leaves, even if they return an annotation.</p>
<pre lang="java">@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@CompositeAnnotation
public @interface DoubleOhAgentCompositeAnnotation {
    // not a leaf annotation - not even an annotation type!
    int numberOfKills();

    // also not a leaf annotation, thus rather pointless to include
    Department employer default @Department("MI6");

    @LeafAnnotation
    CodeNumber codeNumberLeafAnnotation;

    @LeafAnnotation
    Clearance clearanceLeafAnnotation default @Clearance(SECRET);
}
</pre>
<p>As indicated in the comments, whilst there is nothing wrong with declaring non-leaf annotation members in the composite, it doesn&#8217;t make much sense, in general, because the only purpose of the composite is to be expanded. </p>
<p>The values that will be returned for the leaf annotations are the values of the members of the composite instance that is being expanded. So the following composite instance</p>
<pre lang="java">@DoubleOhAgentCompositeAnnotation(numberOfKills = 36, codeNumberLeafAnnotation = @CodeNumber("006"))
Agent jackGiddings;
</pre>
<p>would expand to <tt>@CodeNumber("006")</tt>, <tt>@Clearance(SECRET)</tt>, and</p>
<pre lang="java">@DoubleOhAgentCompositeAnnotation(numberOfKills = 103, codeNumberLeafAnnotation = @CodeNumber("007"),
    clearanceLeafAnnotation = @Clearance(TOP_SECRET))
Agent jamesBond;
</pre>
<p>to <tt>@CodeNumber("007")</tt>, <tt>@Clearance(TOP_SECRET)</tt>.</p>
<p>Specifying good defaults almost always makes sense (if nothing else, it saves on typing!), but as you can see they can always be overriden, if required.</p>
<h4>Writing leaf annotation factories</h4>
<p>So what about this mysterious <tt>numberOfKills</tt> member? It&#8217;s not of an annotation type, so certainly can&#8217;t be a leaf. Moreover, it doesn&#8217;t even have a default value, which means it must be specified every time the composite is used! Annoying, or what?</p>
<p>Well, I&#8217;ll be getting to that. For now, it&#8217;s worth bearing in mind that, whilst defining leaf annotations using defaults is already convenient, it&#8217;s still <em>static</em> &#8211; the defaults are fixed in the definition, and even overriding defaults can only be done using values known at <em>compile</em>-time.</p>
<p>But what if the value of a leaf annotation depended on some runtime property &#8211; oh, I don&#8217;t know, the time of day, the phase of the moon? Or if there was some non-trivial business logic involved that we would rather not have to carry out &#8220;by hand&#8221;, as we would have to in order to specify the value at compile time? </p>
<p>Not that these cases are likely to occur often, but when they do, it would sure be nice to be able to generate the appropriate leaf annotation value <em>dynamically</em>.</p>
<p>This is where <a href="http://code.google.com/p/aphillips/source/browse/at-composite/trunk/src/main/java/com/qrmedia/pattern/compositeannotation/api/LeafAnnotationFactory.java" target="_new">LeafAnnotationFactory</a> comes in<sup>2</sup>. It generates a leaf value based on the composite annotation instance the leaf is declared in &#8211; and whatever else you can lay your hands on at runtime&#8230;even the phase of the moon, if you like.</p>
<p>As an example, assume that we wish to calculate a &#8220;danger rating&#8221; for our 00 agents:</p>
<pre lang="java">@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@CompositeAnnotation
public @interface DoubleOhAgentCompositeAnnotation {
    ...
    @LeafAnnotation
    Rating ratingLeafAnnotation;
}
</pre>
<p>The current rules indicate that any agent with more than 100 kills &#8211; ah, yes, the <tt>numberOfKills</tt> member &#8211; is considered extremely dangerous. </p>
<p>Of course, we know that Maj. Jack Giddings is below and Bond above the limit, so we could just set the values at compile time.</p>
<pre lang="java">@DoubleOhAgentCompositeAnnotation(numberOfKills = 36, codeNumberLeafAnnotation = @CodeNumber("006"),
    ratingLeafAnnotation = @Rating(DANGEROUS))
Agent jackGiddings;

@DoubleOhAgentCompositeAnnotation(numberOfKills = 103, codeNumberLeafAnnotation = @CodeNumber("007"),
    clearanceLeafAnnotation = @Clearance(TOP_SECRET),
    ratingLeafAnnotation = @Rating(EXTREMELY_DANGEROUS))
Agent jamesBond;
</pre>
<p>But what if Her Majesty&#8217;s government, in a fit of political correctness, lowers the limit to 30? Will we remember to adjust the annotations? Will we want to do it for all of our agents?</p>
<p>No, better to generate the correct value for <tt>ratingLeafAnnotation</tt> at runtime.</p>
<pre lang="java">@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@CompositeAnnotation
public @interface DoubleOhAgentCompositeAnnotation {
    int numberOfKills();
    ...
    /*
     * The default will be *ignored* - the factory is always called - but it is more
     * convenient to provide it to prevent the compiler from prompting for one.
     */
    @LeafAnnotation(factoryClass = RatingLeafAnnotationFactory.class)
    Rating ratingLeafAnnotation default @Rating(DANGEROUS);
}

class RatingLeafAnnotationFactory
        implements LeafAnnotationFactory<Rating, DoubleOhAgentCompositeAnnotation> {
    private static final int EXTREME_DANGER_THRESHOLD = 100;

    public Rating newInstance(
            DoubleOhAgentCompositeAnnotation declaringCompositeAnnotation) {
        return RuntimeConfiguredAnnotationFactory.newInstance(Rating.class,
                MapUtils.<String, Object>toMap("value",
                        (declaringCompositeAnnotation.numberOfKills() > EXTREME_DANGER_THRESHOLD)
                        ? Rating.EXTREMELY_DANGEROUS
                        : Rating.DANGEROUS));
    }

}

// @Rating calculated based on the number of kills
@DoubleOhAgentCompositeAnnotation(numberOfKills = 36, codeNumberLeafAnnotation = @CodeNumber("006"))
Agent jackGiddings;

@DoubleOhAgentCompositeAnnotation(numberOfKills = 103, codeNumberLeafAnnotation = @CodeNumber("007"),
    clearanceLeafAnnotation = @Clearance(TOP_SECRET))
Agent jamesBond;
</pre>
<p>Now all we need to adapt to the new rules is to modify the <tt>EXTREME_DANGER_THRESHOLD</tt> in the factory<sup>3</sup>! </p>
<p>Note that the default defined (somewhat counter-intuitively, perhaps) for <tt>ratingLeafAnnotation</tt> has <u>no</u> effect on the value: the factory is always called. But without a default the compiler will prompt for a value for the member whenever the composite is used.</p>
<h3>Usage guidelines</h3>
<p>In order to forestall any chance of your mind taking off on imagining all the things one might do with this, a few sobering points:</p>
<ul>
<li>Firstly, remember that <strong>@Composite</strong> currently <strong>only</strong> works if annotation reflection is done via the <a href="http://code.google.com/p/aphillips/source/browse/at-composite/trunk/src/main/java/com/qrmedia/pattern/compositeannotation/api/AnnotatedElements.java" target="_new">AnnotatedElements</a> interface. <tt>Class.getAnnotation(...)</tt> will <em>not</em> work here!</li>
<li>This also means that, regrettably, <strong>@Composite</strong> will not work for Hibernate, Spring or any other framework that internally uses &#8220;regular&#8221; methods to access annotation information.<sup>4</sup></li>
<li>For the same reasons, <strong>@Composite</strong> should <strong>not</strong> be used to provide annotations which are used by Java itself, e.g. <tt>@Target</tt> or <tt>@Retention</tt>, as these won&#8217;t be visible to the compiler! So please don&#8217;t go about copying the demo <img src='http://blog.xebia.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
</ul>
<h4>Restrictions</h4>
<p>Apart from the above guidelines, there are a number of intentional limitations in the use of composites, whose aim is to make sure that <strong>@Composite</strong> does not allow you to work around restrictions on the use of &#8220;regular&#8221; annotations. This ensures that annotation semantics remain consistent with regular Java.</p>
<p>Which means that, amongst others:</p>
<ul>
<li>There may also only be one leaf annotation of a given type per composite.</li>
<li>The target of a leaf annotation must match that of the composite annotation in which it is declared.</li>
<li>There may not be more than one annotation of the same type on a given element, whatever the regular and composite annotations on that element.</li>
</ul>
<p>For the full list, see <a href="http://code.google.com/p/aphillips/source/browse/at-composite/trunk/src/main/java/com/qrmedia/pattern/compositeannotation/annotation/LeafAnnotation.java" target="_new">LeafAnnotation</a> and <a href="http://code.google.com/p/aphillips/source/browse/at-composite/trunk/src/main/java/com/qrmedia/pattern/compositeannotation/annotation/CompositeAnnotation.java" target="_new">CompositeAnnotation</a>.</p>
<h5>Using the validation processor</h5>
<p>In most of the above cases, <strong>@Composite</strong> will fail early, at the moment the <tt>AnnotatedElements</tt> instance is created. Still, it would be nicer if invalid configurations &#8211; and as we have seen, there are quite a few ways of creating those &#8211; could be detected before we even <em>get</em> to runtime.</p>
<p>To help accomplish this, <strong>@Composite</strong> includes a <a href="http://code.google.com/p/aphillips/source/browse/at-composite/trunk/src/main/java/com/qrmedia/pattern/compositeannotation/validation/CompositeAnnotationValidationProcessor.java" target="_new">validation processor</a>, which is a Java 6 <a href="http://java.sun.com/javase/6/docs/api/javax/annotation/processing/Processor.html" target="_new">annotation processor</a><sup>5</sup>. If you&#8217;re running on Java 6, the processor will automatically run at compile-time<sup>6</sup> and fail, with hopefully useful error messages, if <strong>@Composite</strong> is not being used correctly. You can also add  validation processing to your Eclipse project &#8211; see the <tt>CompositeAnnotationValidationProcessor</tt> Javadoc for details.</p>
<p>For a demonstration of the validation processor, check out the <tt>at-composite-validator-demo</tt> project (<a href="http://aphillips.googlecode.com/svn/at-composite-validator-demo/trunk/" target="_new">http://aphillips.googlecode.com/svn/at-composite-validator-demo/trunk/</a>) and try to build it!</p>
<h3>Integrating with Spring</h3>
<p><strong>@Composite</strong> wouldn&#8217;t be a self-respecting Java project if it didn&#8217;t offer some kind of Spring integration now, would it<sup>7</sup>? Thankfully, there&#8217;s not much to do here &#8211; simply create an instance of<br />
<tt>AtCompositeAnnotatedElements</tt> (which can be a singleton), passing a list of the composite annotation types to be supported.</p>
<p><tt>AtCompositeDemo</tt> already demonstrates how to use <strong>@Composite</strong> with Spring, and more information can be found in the <tt>AtCompositeAnnotatedElements</tt> Javadoc.</p>
<h3>Getting <strong>@Composite</strong></h3>
<p>The <strong>@Composite</strong> source code, and that for non-standard dependencies, is available at <a href="http://code.google.com/p/aphillips/" target="_new">Google Code</a>. </p>
<h4>Maven</h4>
<p>If you&#8217;re using Maven, the relevant dependency is</p>
<pre lang="xml">  <dependency>
    <groupId>com.qrmedia.pattern</groupId>
    <artifactId>at-composite</artifactId>
    <version>1.0-SNAPSHOT</version>
  </dependency>
</pre>
<p>and you&#8217;ll need to add the following repository to your POM.</p>
<pre lang="xml">  <repository>
    <id>qrmedia-releases</id>
    <url>http://qrmedia.com/mvn-repository</url>
  </repository>
</pre>
<div style="background-color: #EFEEEA; border: 1px solid #AAAAAA; margin: 0.8em; padding: 0.4em; font-size: 85%;">
<strong>Footnotes</strong></p>
<ol>
<li>Although that would probably make an interesting follow-up project!</li>
<li>I studiously ignored its appearance in the demo, but I&#8217;m pretty sure I didn&#8217;t manage to sneak it past all of you <img src='http://blog.xebia.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
<li><a href="http://code.google.com/p/aphillips/source/browse/commons-annotation-utils/trunk/src/main/java/com/qrmedia/commons/lang/annotation/factory/RuntimeConfiguredAnnotationFactory.java" target="_new">RuntimeConfiguredAnnotationFactory</a> is just a convenient way of generating a runtime annotation instance, but well worth a look&#8230;if only to see that it&#8217;s probably simpler than one might expect!</li>
<li>I suspect, though, that it wouldn&#8217;t be too hard to adapt such frameworks to use <strong>@Composite</strong>, since it is fully &#8220;backwards-compatible&#8221; with regular Java annotations. With judicious use of <a href="http://eclipse.org/aspectj/" target="_new">aspects</a>, there might even be a way of &#8220;retro-fitting&#8221; this onto existing code.</li>
<li>Testing the annotation processor proved rather less straightforward than I first imagined, but that&#8217;s a story for another blog post.</li>
<li>You can suppress annotation processing by passing a <tt>-proc:none</tt> argument to the compiler. See the <a href="http://java.sun.com/javase/6/docs/technotes/tools/windows/javac.html#processing" target="_new">javac docs</a>.</li>
<li>Although I have to confess to secret <a href="http://code.google.com/docreader/#p=google-guice&#038;s=google-guice&#038;t=Motivation" target="_new">Guice</a> leanings of late <img src='http://blog.xebia.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
</ol>
</div>
<div name="googleone_share_1" style="position:relative;z-index:5;float: right; margin-left: 10px;"><g:plusone size="small" count="1" href="http://blog.xebia.com/2009/06/23/composite-macro-annotations-for-java/"></g:plusone></div><p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fblog.xebia.com%2F2009%2F06%2F23%2Fcomposite-macro-annotations-for-java%2F&amp;title=%40Composite%20%26%238211%3B%20Macro%20Annotations%20for%20Java" id="wpa2a_2"><img src="http://blog.xebia.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.xebia.com/2009/06/23/composite-macro-annotations-for-java/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  blog.xebia.com/tag/annotation/feed/ ) in 0.58313 seconds, on Feb 9th, 2012 at 3:55 pm UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on Feb 9th, 2012 at 4:55 pm UTC -->
