blob: a0c9b753355a64fbc501bd037d7c0db5027ea9d2 [file] [log] [blame]
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>JAM - The Java API for Metadata</title>
<link href="jam.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>JAM - Overview</h1>
<p>
JAM is an object model for Java types and their associated annotations.
It provides a superset of the features offered by similar APIs
(such as Reflection or X/Javadoc), including a unique extensibility
mechanism specifically designed to help Java developers cope with the
rapidly-changing world of Java metadata.
<h3>Why?</h3>
<p>
There already are a number of ways in which you can inspect and
model Java types. Java reflection, of course, can be used to
introspect loaded classes, while tools such as X/Javadoc or Qdox
can parse java sources and give you model of their contents
(including comments and other information that is lost during java
compilation).
</p>
<p>
But consider the case where you want to inspect a set of java types
where you have source files for some of the types, but only classfiles
for others. And what if you want to be able to access the comments
for your java types when they are available from source, but still
process them sans comments when you only have classfiles? One approach
would be to write one version of your program's logic that works
against the Reflection API, and another that works with Javadoc's
Doclet API. But that seems rather painful - isn't there a better
way?
</p>
<h3>Artifact Agnosticism</h3>
<p>
JAM solves this (and many other problems, as we will see) by creating
an insulating layer between your code and the real artifacts which
describe the java types your code needs to view. The JAM API was
designed from the ground up to allow you to write code that is
completely <i>artifact agnostic</i> when inspecting java types.
That is to say, JAM provides a set of
abstractions which isolate your java type-inspecting code from the
files that it is actually looking at. This means that you get a
single API with which you can view java sources and classfiles.
</p>
<p>
For example, a given instance of JClass (JAM's abstract representation
of a Java class) may in reality represent the contents of either a
<code>.class</code> file or its corresponding <code>.java</code>
source file. However, the JClass that your code sees looks exactly
the same in either case. Without JAM, you may have to write your code
twice using two separate APIs like Javadoc and Reflection. With JAM,
your code more able to focus on the logic that is central to your
application.
</p>
<h3>Extensibility</h3>
<p>
However, the advantages of JAM's proxy-based design extend far
beyond simply providing a unified view of java source- and
classfiles. This is because JAM allows you to write your own
extensions which customize the proxies that it creates. With this
extension mechanism, you can easily add, modify, or remove any
part of a proxy being built.
</p>
<p>
For example, you could write an extension which adds a default comment
to uncommented methods on a given JClass. With such an extension
in place, JClasses loaded by JAM will contain your generated comments
<i>exactly as if they had actually been in the source file all along.</i>
</p>
<p>
Even though this is an extremely simple example, consider how much
trouble it might save you in a complex application composed of serveral
subsystems. Say that those subsystems who ask each other to do things
using java types that they pass around, and that we need them to use
default comments. If we don't have JAM, we're going to have to write
special logic in each subsystem to generate default comments when
appropriate. However, with JAM, we only have to write one bit of code
that weaves those comments into out proxied view of the Java classes.
Those subsytems that are consuming this view need be none the wiser.
</p>
<h3>JSR175: The New Metadata Frontier</h3>
<p>
JAM's extensibility makes it ideally suited to help Java developers
tackle a large problem looming on the horizon:
<a href='http://www.jcp.org/en/jsr/detail?id=175'>JSR175</a>,
"A Metadata Facility for Java." New to JDK 1.5, this specification
introduces a
builtin mechanism for marking up java code with metadata, a job which
historically has been done with javadoc tags. JSR175 introduces
changes to both the Java Language Specification (for declaring metadata)
and the Reflection API (for accessing metadata) in order to bring
structure and strong typing to java metadata.
</p>
<p>
These are huge improvements are desperately needed in the Java
community. However, big changes usually mean pain for developers,
and JSR175 is no exception. The primary challenge with JSR175 lies
in the simple fact that it is not backward-compatible with earlier
JDKs - you cannot use it without JDK1.5.
</p>
<p>
Of course, this is not a problem developers who do not care about
metadata, or least not about JSR175-style metadata. It's also not
a problem for developers who do care about JSR175 but who
<ul>
<li>are working on brand new applications using JDK 1.5 and</li>
<li>will be able to require their users to upgrade to JRE 1.5</li>
</ul>
</p>
<p>
If you are fortunate enough to be one of these developers,
you get to start with a clean slate with JDK 1.5, use JSR175,
and not worry about anything. (Well, not quite - there actually are
still a <a href='typedMetadata.html'>a number of reasons</a> why
even you should consider using JAM for metadata access).
</p>
<p>
For everyone else, though, it's going to be a big problem, and it will
continue to be a problem for the forseeable future. Developers who
need to support JSR175 metadata under 1.5 while continuing to support
older javadoc-style annotations under 1.4 face a daunting task.
They must be able to retrieve very
different metadata structures from different APIs. They
must then somehow structure their program code to respond appropriately
(and consistently) in either case.
</p>
<p>
JAM's extensibility can help in a big way here. Remember how JAM
lets you be agnostic about whether you were looking at a source-
or class file? Well, exactly the same principle can be brought to bear
on other kinds of artifacts. As before, we want to have unified
view of two kinds of artifacts (javadoc tags and JSR175 annotations)
that really mean the same thing to our code. JAM can give you a
unified view of your java metadata, one that looks the same whether
it is javadoc- or JSR175-based.
</p>
<p>
Unless your metadata is very simple, JAM will probably need a little
bit of help from you to do this correctly. JAM's specialized
extension mechanism for annotations allows you to easily customize how
tag and JSR175 annotation values are mapped into the JAM object that
will act as a proxy for your metadta. In this way, the
mapping logic remains encapsulated, away from the parts of your code
that are actually trying to do something interesting with the metadata.
</p>
<p>
JAM will even let you define strongly-typed proxies so that you can get
the same kind of bean-like access to your metadata that JSR175 offers.
The big difference is that with JAM, your code will be able to
transparently understand javadoc tags and it will still run under
JRE 1.4.
</p>
<h3>Conclusion</h3>
<p>
If you are working on a project where you need to understand
what java classes look like, you should consider using JAM. It
allows you to loosely-couple your application from the way in which
the java classes are parsed or loaded, and it's extensibility
features can allow you to implement elegant solutions to complex
problems involving java type introspection. And finally, if JSR175
if causing you grief, JAM can help.
</p>
</body>
</html>