460 likes | 698 Views
Using Java Annotations in Eclipse. Gary Horen BEA Systems Tim Wagner BEA Systems. Agenda. Background Simple Example Demo Mirror API and APT Pitfalls More Elaborate Example Futures. What are annotations?. Metadata placed directly in your source code
E N D
Using Java Annotationsin Eclipse Gary Horen BEA Systems Tim Wagner BEA Systems
Agenda • Background • Simple Example Demo • Mirror API and APT • Pitfalls • More Elaborate Example • Futures
What are annotations? • Metadata placed directly in your source code • Standardized by JSR 175, added to Java in 1.5 • Intended to replace “xdoclet”-style programming with a modern, type-checked equivalent @MyAnnotation(num=5, str=“hi”) public class Foo { … }
What are annotations? • Defined using Java – much like interfaces • Can be used by both tools and runtimes • Enable a simpler “POJO”-based programming model public @interface MyAnnotation { int num; String str; }
What can an annotation do? • Example: helping a POJO to become a web service • Annotations on user code generate helper objects • Endpoint interface: receives and parses XML message • Bindings embody the message as parameters to the POJO method Endpoint Interface generates @WebservicePublic class Foo { } XML-Java Bindings
Who uses annotations? • J2SE – builtin annotations • J2EE – EBJ 3.0, JSR 181, JSR 250, JAXB 2.0, JAX-WS 2.0 • 3rd party frameworks: Hibernate, Beehive, Spring • …and eventually every major IT organization @Deprecated @WebService @Persistent @MyCorporateAnnotation
Build-time uses • Many annotations effects happen at build time, not run time • “I need to create a stub/skeleton that matches this interface” • “I need to inform my container that I need resource X” • “I need to verify that this method meets some constraints” • We need several things to make this useful • Something to process a set of annotations – an annotation processor • A build (compile) time container for these processors – a compiler with extra smarts • Enhanced visual tools – make Eclipse aware of the special semantics of annotations
Process view Processor Container Annotated Source File apt tool in JDK 1.5 or Eclipse apt plugin @MyAnno public class Foo { ... } compiles calls @MyAnno processor another processor
What can an annotation processor do? • Can • Claim a set of annotations • Check annotations for semantic errors • Generate new Java source files • Generate arbitrary data files (e.g. deployment descriptor) • Cannot • Change the bytecode generated when the file is compiled in any way
Demo • DemoAnnotation • An Annotation contains elements • Elements contain names and values • An annotation processor can check element values for correctness • TypeGeneratingAnnotation • Generates a Java source file
Agenda • Background • Simple Example Demo • The mirror API and APT • Pitfalls • More Elaborate Example • Futures
What you need to provide • Step 1: Locate or write your own annotation(s) public @interface MyAnnotation { int num; String str; }
What you need to provide • Step 2: Write an annotation processor factory import com.sun.mirror.apt.*; public class MyAnnotationFactory implements AnnotationProcessorFactory { AnnotationProcessor getProcessorFor() … }
What you need to provide • Step 3: Write an annotation processor import com.sun.mirror.apt.*; public class MyAnnotationProcessor implements AnnotationProcessor { void process() }
Packaging • You provide • The annotation declaration • An implementation of AnnotationProcessorFactory • An implementation of AnnotationProcessor • These are packaged in a jar • Processor runs inside a dispatching framework • Command line APT • org.eclipse.jdt.apt.core plugin
Environment APIs Annotation Processor Environment @Foo @Bar @Baz ... a d c b Declarations to process Type system exploration File generation Error messages
Using AnnotationProcessorEnvironment AnnotationProcessorEnvironment getDeclarationsWith(annotation) Declaration getAnnotationMirrors() AnnotationMirror getElementValues() Element map
Processing rounds Round 1: Original source files Round 2: Types generated by processing original files in round 1 Round 3: Types generated in round 2
“Write once” – processor reuse apt tool in JDK 1.5 or Eclipse apt plugin Eclipse apt plugin or apt tool in JDK 1.5 @MyAnno processor
Dispatching: command line support • apt • Tool available in JDK 1.5 (along with javac, javadoc, javap, etc.) • Works like javac, but with something extra: It runs 3rd party annotation processors in addition to compiling source code • Any generated types also get compiled • Locates factories through META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory file: • Each line of file = fully qualified factory class name % apt –classpath Proc.jar MyProgram.java
Dispatching: inside Eclipse • From a jar file external to the workspace • Classpath variables provide indirection • From a jar file inside a project • Static jar only: jar file may not be rebuilt in same workspace that uses it • Jar file must be available on the Eclipse Java compiler runtime classpath • From a plugin • <extension point=org.eclipse.jdt.apt.core.annotationProcessorFactory> • Debugging must be done in plugin: • Build in development workspace • Run on annotated source in debugged workspace
Agenda • Background • Simple Example Demo • The mirror API and APT • Pitfalls • More Elaborate Example • Futures
Pitfall: APT round implemenation All of round 1 runs first @Fooclass Quack @Gooclass Moo @Rooclass Mumble Round 1 Then all of round 2 @Barclass GenMoo @Barclass GenQuack @Barclass GenMumble Round 2
Pitfall: Eclipse round implementation Dispatch all this Then this Then this @Fooclass Quack @Gooclass Moo @Rooclass Mumble Round 1 @Barclass GenQuack @Barclass GenMumble @Barclass GenMoo Round 2 Rounding in Eclipse must be file-at-a-time for performance reasons.
Pitfall: gathering generated files @Fooclass Quack @Gooclass Moo @Rooclass Mumble • Don’t do this. It depends on dispatcher implementation. • Instead: gather generated files in a post-build step. Round 1 generates Goo.xml Roo.xml Foo.xml @Barclass GenX Round 2 reads all
Pitfall: processor requests generated type @Gooclass Moo @Fooclass Quack • Don’t do this. It depends on visibility of generated types. • But: generated types can refer to other generated types. Round 1 generates @Barclass GenFoo class GenGoo Round 2 generates Anno processor requests: not OK class GenBar Generated type refers to: OK
Pitfall: APT round implemenation All of round 1 runs first @Fooclass Quack @Gooclass Moo @Rooclass Mumble Round 1 Then all of round 2 @Barclass GenMoo @Barclass GenQuack @Barclass GenMumble Round 2
Pitfall: build vs. reconcile • Interactive (as you type) compilation = reconcile • Can’t put new files on disk • File generation happens only during build • Best practice: build your workspace before you edit • Then reconcile can see generated types • Less confusion for the user • Set project autobuild (build on Save) to “on” • Keep build current • Hopefully reconcile limitation goes away in next release
Agenda • Background • Simple Example Demo • The Mirror API and APT • Pitfalls • More Elaborate Example • Futures
Example: the Chargeable annotation App developer annotates a class to use the accounting system: • Class level annotation: @Chargeable • Method level annotations: • @ChargePerCall(amount = 0.003) • @ChargeWallClockTime • @NoCharge
What does @Chargeable do? • Generates wrapper class with proxy method that posts charge • Generates ISomeService interface; both wrapper and app class implement • Generates factory that creates the wrapped SomeService class class SomeServiceWrapper private SomeService _service; class SomeService public executeRequest() start = currentTimeMillis();_service.executeRequest();AccountSystem.charge( currentTimeMillis() – start); @ChargeWallClockexecuteRequest()
Code Snippet: using @Chargeable @Chargeablepublic class AnalysisService { @ChargeWallClockTime public ResultSet executeQuery(String key) { … } @ChargePerCall(amount = .007) public int findMedianSalary(ResultSet res) { … } @NoCharge public int findMeanSales(ResultSet res) { … }
@Chargeable generates source files Generated source User’s code
Agenda • Background • Simple Example Demo • The Mirror API and APT • Pitfalls • More Elaborate Example • Futures • JSR 269 • UI Enhancements
JSR 269 • Annotations already standard language feature (JSR 175) • Standard annotations exist for specific applications (JSR 181, 220) • The mirror API is a preview interface (com.sun.mirror) • Sun has announced intention to open-source interfaces • JSR 269 will standardize the processor API (in javax package space) • Specification will wrap up soon, to be available in Java SE 6 • Target Eclipse availablity: 3.2 • Mirror support continues in Eclipse until 269 widely adopted
User Interface APIs Eclipse apt plugin @MyAnno processor factory
Eclipse-specific functionality • Code assistance inside annotation values • Auto-completion • Quick-fix • Visual editing • A special viewer/editor for annotations • Refactoring • Participation in rename operations • Find-uses
Code assistance: auto-completion • User presses Ctrl-space • Annotation processor proposes content
Code assistance: quick-fix • Annotation processor posts an error or warning • User presses Ctrl-1 • Annotation processor can propose fixes to the user
Visual Annotation Editor • Show complex annotations in friendlier way • Property pane-like UI • Values in code in bold typeface • Defaulted values in normal typeface • Make nested annotations understandable @MyService( buffer = @MessageBuffer(enable = true), conversation = @Phase(“start”))public boolean testVerifyFunds(Mumble m){ … }
Release Timeline: APT in Eclipse JUN JUL AUG SEP OCT NOV DEC JAN FEB MAR APR JUN 3.1 3.2 3.1.1 Alpha (core) Beta (UI Features) APT released as part of JDT
Q & A Try it out! Download and install at:http://www.eclipse.org/jdt/apt/introToAPT.html
Using Java Annotationsin Eclipse Gary Horen BEA Systems Tim Wagner BEA Systems