Showing that no rule is so broad as to not admit an exception, the apt
tool and its associated API, com.sun.mirror.\*
,
are being deprecated in JDK 7.
The plan is to remove the tool and its API to the next major JDK release after JDK 7.
As a com.sun.\*
API, the apt
API is not governed by the JCP; however, we don't usually mass-deprecate com.sun.\*
APIs either. We introduced apt
in JDK 5 to gain experience with annotation processing before standardizing this facility with
JSR 269 in JDK 6, which added the javax.annotation.processing
and javax.lang.model.\*
packages and added annotation processing options to javac
.
As the lead engineer for both apt
and JSR 269, the JSR 269 API and tool experience should be uniformly better than apt
; the newer API is easier to use, more flexible, and should run faster as well. I unconditionally recommend transitioning to the JSR 269 API and javac
(or its
compiler API) for all your annotation processing needs.
The table below summarizes the apt
deprecation information.
apt type | Standard Replacement |
---|---|
Package com.sun.mirror.apt | |
AnnotationProcessor | javax.annotation.processing.Processor |
AnnotationProcessorEnvironment | javax.annotation.processing.ProcessingEnvironment |
AnnotationProcessorFactory | javax.annotation.processing.Processor |
AnnotationProcessorListener | No analog. |
AnnotationProcessors | No analog. |
Filer | javax.annotation.processing.Filer |
Filer.Location | javax.tools.StandardLocation |
Messager | javax.annotation.processing.Messager |
RoundCompleteEvent | No analog. |
RoundCompleteListener | No analog. |
RoundState | javax.annotation.processing.RoundEnvironment |
Package com.sun.mirror.declaration | |
AnnotationMirror | javax.lang.model.element.AnnotationMirror |
AnnotationTypeDeclaration | javax.lang.model.element.TypeElement |
AnnotationTypeElementDeclaration | javax.lang.model.element.ExecutableElement |
AnnotationValue | javax.lang.model.element.AnnotationValue |
ClassDeclaration | javax.lang.model.element.TypeElement |
ConstructorDeclaration | javax.lang.model.element.ExecutableElement |
Declaration | javax.lang.model.element.Element |
EnumConstantDeclaration | javax.lang.model.element.VariableElement |
EnumDeclaration | javax.lang.model.element.TypeElement |
ExecutableDeclaration | javax.lang.model.element.ExecutableElement |
FieldDeclaration | javax.lang.model.element.VariableElement |
InterfaceDeclaration | javax.lang.model.element.TypeElement |
MemberDeclaration | javax.lang.model.element.Element |
MethodDeclaration | javax.lang.model.element.ExecutableElement |
Modifier | javax.lang.model.element.Modifier |
PackageDeclaration | javax.lang.model.element.PackageElement |
ParameterDeclaration | javax.lang.model.element.VariableElement |
TypeDeclaration | javax.lang.model.element.TypeElement |
TypeParameterDeclaration | javax.lang.model.element.TypeParameterElement |
Package com.sun.mirror.type | |
AnnotationType | javax.lang.model.type.DeclaredType |
ArrayType | javax.lang.model.type.ArrayType |
ClassType | javax.lang.model.type.DeclaredType |
DeclaredType | javax.lang.model.type.DeclaredType |
EnumType | javax.lang.model.type.DeclaredType |
InterfaceType | javax.lang.model.type.DeclaredType |
MirroredTypeException | javax.lang.model.type.MirroredTypeException |
MirroredTypesException | javax.lang.model.type.MirroredTypesException |
PrimitiveType | javax.lang.model.type.PrimitiveType |
PrimitiveType.Kind | javax.lang.model.type.TypeKind |
ReferenceType | javax.lang.model.type.ReferenceType |
TypeMirror | javax.lang.model.type.TypeMirror |
TypeVariable | javax.lang.model.type.TypeVariable |
VoidType | javax.lang.model.type.NoType |
WildcardType | javax.lang.model.type.WildcardType |
Package com.sun.mirror.util | |
DeclarationFilter | javax.lang.model.util.ElementFilter |
DeclarationScanner | javax.lang.model.util.ElementScanner6 |
DeclarationVisitor | javax.lang.model.element.ElementVisitor |
DeclarationVisitors | No replacement. |
Declarations | javax.lang.model.util.Elements |
SimpleDeclarationVisitor | javax.lang.model.util.SimpleElementVisitor6 | SimpleTypeVisitor | javax.lang.model.util.SimpleTypeVisitor6 | SourceOrderDeclScanner | javax.lang.model.util.SimpleElementVisitor6 |
SourcePosition | No replacement. | TypeVisitor | javax.lang.model.element.TypeVisitor | Types | javax.lang.model.util.Types |
Good riddance! Too bad apt was not deprecated in Java SE 6 so we could totally kill it now.
Suggestion: unbundle this turd from the JDK now, keeping it available as a separate download -- with "unsupported" status and deprecation tags -- for people who need it. There is no reason that stuff that's (a) deprecated, (b) planned for total elimination in next release, should be conveniently bundled in the JDK.
JSR-269 has been available for 2.5 years since Java SE 6 so you must assume that only the most lazy or conservative users are still depending on apt; some people follow too hard the "if it ain't broken, don't fix it" rule. These are exactly the users who will typically ignore deprecation warnings, and they will be still using apt when JDK 8 ships completely without apt.
You do a favor to these laggards to make a bit harder to use apt with JDK 7; with unbundling, they will see their builds breaking and be forced to download and install apt separately. This should be enough "writing on the wall" to make people migrate faster.
Remember that the Java platform has a long tradition of never removing any legacy feature, we have all garbage deprecated in JDK1.1 and up still in the latest version. So many developers get used to simply ignore deprecation in core libs.
I'm currently using apt for its SourcePosition information, which isn't available in JSR 269. Too bad for me!
In spite of that, I think this is the right move.
Jesse,
The Tree API of JDK6 provides a much richer API for getting source positions. The API focuses on character offsets in files, rather than lines and columns which simply doesn't provide a good canonical representation.
However, it is a little expensive for the compiler to account for all the source positions, so we didn't make them first class citizens in the API. Here is a collection of all the relevant API:
http://java.sun.com/javase/6/docs/technotes/guides/javac/index.html
The first thing you need to do is get an instance of Trees using this method: http://java.sun.com/javase/6/docs/jdk/api/javac/tree/com/sun/source/util/Trees.html#instance(javax.annotation.processing.ProcessingEnvironment)
Now that you have this instance, grab an instance of the sources positions utility using getSourcePositions().
Use the Trees instance to get the path of an element using getPath().
From the path you can get the compilation unit and leaf node. Use them to get a start or end position from the SourcePositions instance. These positions are character offsets from the beginning of a file, you can convert them to lines and columns using the line map of the compilation unit.
I know this is a complex API compared to com.sun.mirror, but we felt it was important to be able to expose the underlying representation inside javac directly without building heavy wrapper objects thus sacrificing speed and memory footprint. We hope the exposed API is flexible enough to not constrain future optimizations of javac. I think you will find that annotation processing inside javac is much faster than apt. All the element, type, and tree objects that you get are the objects used directly inside javac, not costly wrapper objects with slightly out-of-sync semantics.
Cheers,
Peter
@Jesse and @Peter,
Within the apt API, source positions are only consumed by the Messager. Because of that, in JSR 269 we just pass elements in question to the Messager to allow the source position to be implicitly reconstructed.
If you need the source positions for some other purpose, Peter's suggestion of using the tree API is the right approach.
Joe,
I thought the replacements you listed are already available in Java 6? At least I can't find javax.annotation.processing.ProcessingEnvironment for example. I have to migrate an apt based model driven development approach and would appreciate any hints to good documentation, tutorials, migration guides ...
Cheers,
Roger
@Roger,
Yes, all the replacements are available as of JDK 6; the type in question is documented at
http://java.sun.com/javase/6/docs/api/javax/annotation/processing/ProcessingEnvironment.html
See slides 56 and 57 of the 2006 JavaOne talk
"Annotation Processing With JSR 269,"
by Joseph D. Darcy, Scott Seligman, Jess Garms, Bruce Chapman
to get an overview of some of the fundamental changes between apt the the JSR 269-based annotation processing in javac.
@Joe,
sorry! It was right before my eyes!
Cheers,
Roger