Presentation is loading. Please wait.

Presentation is loading. Please wait.

Fun with Java Annotations Brian McGinnis. Java Annotations Introduced in “Tiger” release (Java 1.5) Introduced in “Tiger” release (Java 1.5) One of most.

Similar presentations


Presentation on theme: "Fun with Java Annotations Brian McGinnis. Java Annotations Introduced in “Tiger” release (Java 1.5) Introduced in “Tiger” release (Java 1.5) One of most."— Presentation transcript:

1 Fun with Java Annotations Brian McGinnis

2 Java Annotations Introduced in “Tiger” release (Java 1.5) Introduced in “Tiger” release (Java 1.5) One of most interesting Java extension in a long time One of most interesting Java extension in a long time Ability to declare metadata modifiers for Java language upon: Ability to declare metadata modifiers for Java language upon: Type declarations, Constructors, methods, Members, Parameters, Variables Type declarations, Constructors, methods, Members, Parameters, Variables

3 Standard Java 1.5 Annotations Tiger has some useful built-in annotations Tiger has some useful built-in annotations Java.lang.Override Java.lang.Override Compiler enforces overriding superclass methods Compiler enforces overriding superclass methods Java.lang.Deprecated Java.lang.Deprecated Warns when @deprecated method, class or member is used Warns when @deprecated method, class or member is used Must use javac “-deprecation” argument to javac or the new - Xlint:deprecated flag to see compiler warnings Must use javac “-deprecation” argument to javac or the new - Xlint:deprecated flag to see compiler warnings Java.lang.SupressWarnings Java.lang.SupressWarnings Useful for Tiger’s many compiler warnings (especially with legacy collection code) Useful for Tiger’s many compiler warnings (especially with legacy collection code) Key: Look for a string enclosed in “[ ]” in compiler warnings from javac (may need to use the command line). Use this string to use for the @SuppressWarning argument. Key: Look for a string enclosed in “[ ]” in compiler warnings from javac (may need to use the command line). Use this string to use for the @SuppressWarning argument. This may work on your compiler yet! This may work on your compiler yet!

4 @Override Example @Override Example Code: class Base { public void yes(int i) { } public void yes(int i) { }} class Subclass extends Base { @Override @Override public void yes(int i) { } public void yes(int i) { } @Override @Override public void no(float x) { } // Compiler error generated here! public void no(float x) { } // Compiler error generated here!}

5 @Deprecated Example Example usage: @Deprecated public class DeprecatedExample { private int x; private int x; @Deprecated @Deprecated public int value; public int value; @Deprecated @Deprecated public void setValue(int aValue) { value = aValue; } public void setValue(int aValue) { value = aValue; }} public class DeprecatedExampleUse { public static void main(String argv[]) public static void main(String argv[]) { DeprecatedExample obj = new DeprecatedExample(); // Compiler WARNINGs generated here DeprecatedExample obj = new DeprecatedExample(); // Compiler WARNINGs generated here obj.value = 10; // Compiler WARNING generated here obj.value = 10; // Compiler WARNING generated here }}

6 @SuppressWarning Example public class SuppressExample { List wordList = new ArrayList(); // no typing information on the List List wordList = new ArrayList(); // no typing information on the List private void private void generateWarning() generateWarning() { wordList.add("foo"); // Warning generated here. wordList.add("foo"); // Warning generated here. }} javac -Xlint:unchecked SuppressExample.java SuppressExample.java:13: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.List wordList.add("foo"); // Warning generated here. wordList.add("foo"); // Warning generated here. ^ 1 warning Get rid of warning by adding this line above the method delcaration: @SuppressWarning(“unchecked”)

7 Setting Annotation Values Setting Annotation Values Setting Annotation Values Set arguments as key/value pairs Set arguments as key/value pairs Can optionally be an array of key value pairs Can optionally be an array of key value pairs “Marker” annotations “Marker” annotations No arguments No arguments Example: @Deprecated Example: @Deprecated Single value annotations Single value annotations no key is required, just a value no key is required, just a value Example: @SuppressExample(“unchecked”) Example: @SuppressExample(“unchecked”) Multiple value annotations Multiple value annotations separate key/value pairs with commas separate key/value pairs with commas Example: @Review(student=“Jonny Law”, grade=Grades.Pass) Example: @Review(student=“Jonny Law”, grade=Grades.Pass)

8 Java Annotations Metadata from annotations is available at compile-time and at runtime Metadata from annotations is available at compile-time and at runtime What for? What for? compile-time uses: Tools like a code generator or code validator (e.g. java.lang.Override) compile-time uses: Tools like a code generator or code validator (e.g. java.lang.Override) runtime uses: Any framework or application code that can make use of metadata (e.g. J2EE) runtime uses: Any framework or application code that can make use of metadata (e.g. J2EE)

9 Implementing and using custom annotations

10 A Sample Annotation Application A simple example to demo custom annotations A simple example to demo custom annotations The demo application is: We want to readily identify design patterns used in our production code The demo application is: We want to readily identify design patterns used in our production code Users put in annotation “@Pattern” to identify design patterns in their code Users put in annotation “@Pattern” to identify design patterns in their code Our @Pattern annotation takes 3 arguments: Our @Pattern annotation takes 3 arguments: PatternType = an enum for which design pattern (e.g. singleton, builder, etc.) PatternType = an enum for which design pattern (e.g. singleton, builder, etc.) Role = a string to denote the role played in more complex patterns (e.g. for an MVC pattern, role=“controller”) Role = a string to denote the role played in more complex patterns (e.g. for an MVC pattern, role=“controller”) Msg = a string to further explain pattern usage Msg = a string to further explain pattern usage

11 Sample usage #1 package samples.myapp; import custom.annotation.Pattern; import custom.annotation.PatternType; /** An example singleton that uses our @Pattern annotation. */ @Pattern(type=PatternType.SINGLETON, msg=“Singleton wrapper class”) public class SampleOne { private static SampleOne instance = null; private static SampleOne instance = null; private SampleOne() { } private SampleOne() { } public static SampleOne public static SampleOne get() get() { if (instance == null) if (instance == null) instance = new SampleOne(); instance = new SampleOne(); return(instance); return(instance); }}

12 Sample Usage #2 package samples.myapp; import custom.annotation.Pattern; import custom.annotation.PatternType; /** An example class that uses our @Pattern annotation. */ public class SampleTwo { @Pattern(type=PatternType.FACTORY, role="static factory method") @Pattern(type=PatternType.FACTORY, role="static factory method") public static SampleTwo public static SampleTwo create(int aValue) create(int aValue) { SampleTwo instance = new SampleTwo(aValue); SampleTwo instance = new SampleTwo(aValue); return(instance); return(instance); } private int i; private int i; protected SampleTwo(int a) { i = a; } protected SampleTwo(int a) { i = a; } protected SampleTwo() { } protected SampleTwo() { }}

13 Implementing Annotations 4 standard meta-annotations you need to know about: 4 standard meta-annotations you need to know about: @Target – specifies which Java elements can use the annotation (e.g. Type, method, constructor, etc.) @Target – specifies which Java elements can use the annotation (e.g. Type, method, constructor, etc.) @Retention – specifies if annotation info is available at compile-time or at runtime @Retention – specifies if annotation info is available at compile-time or at runtime @Documented – Indicates if annotation should be part of public api. Annotation use shows up in javadoc. @Documented – Indicates if annotation should be part of public api. Annotation use shows up in javadoc. @Inherited – Specify inheritance handling of the annotation @Inherited – Specify inheritance handling of the annotation

14 Implementing annotations 1. Declare meta-annotations for you custom annotation in the java file Example: @Target, @Documented, etc. Example: @Target, @Documented, etc. 2. Declare an @interface for your custom annotation in the java file Similar to a regular Java ‘interface’ Similar to a regular Java ‘interface’ Define “properties” of the annotation as methods Define “properties” of the annotation as methods

15 Annotation Implementation package custom.annotation; Import …. // Specify our meta-annoations here. @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Documented // Tell javadoc to include usage of our custom annotations public @interface Pattern { // The design pattern enum value for the annotation instance. // The design pattern enum value for the annotation instance. PatternType type(); PatternType type(); // The "role" played in the design pattern. (value is optional) // The "role" played in the design pattern. (value is optional) String role() default "“; String role() default "“; // Some text to be displayed played in the design pattern. (optional) // Some text to be displayed played in the design pattern. (optional) String msg() default ""; String msg() default "";}

16 Annotation Implementation package custom.annotation; /** Declare the design patterns known by our custom @Pattern annotation. */ public enum PatternType { /** A class which wraps a singleton object instance... blah. */ /** A class which wraps a singleton object instance... blah. */ SINGLETON_CLASS, SINGLETON_CLASS, /** A method used to constructs an object instance... blah. */ /** A method used to constructs an object instance... blah. */ FACTORY_METHOD, FACTORY_METHOD, /** A class which is used to... blah. */ /** A class which is used to... blah. */ BUILDER; BUILDER; public static String public static String getHtmlLink(PatternType pattern, String basePath) { … } getHtmlLink(PatternType pattern, String basePath) { … }}

17 Tools to use our custom type At runtime, you can get annotation values from java classes At runtime, you can get annotation values from java classes If you defined the annotation using @Retention(RetentionPolicy.RUNTIME) If you defined the annotation using @Retention(RetentionPolicy.RUNTIME) Use java reflection to pickup annotations from methods, members, etc. Use java reflection to pickup annotations from methods, members, etc. Demo a sample app which prints out all design @Pattern we used in our application code Demo a sample app which prints out all design @Pattern we used in our application code

18 Pattern Tool Source Code public class PatternTool { /** Processes the @Pattern annotations for a java class. The meat of our tool. */ /** Processes the @Pattern annotations for a java class. The meat of our tool. */ private void processPatternAnnotations(Class javaClass) throws IOException private void processPatternAnnotations(Class javaClass) throws IOException { // Get the design @Pattern declared upon class declaration // Get the design @Pattern declared upon class declaration if (javaClass.isAnnotationPresent(Pattern.class)) { if (javaClass.isAnnotationPresent(Pattern.class)) { Pattern classLevelPattern = (Pattern)javaClass.getAnnotation(Pattern.class); Pattern classLevelPattern = (Pattern)javaClass.getAnnotation(Pattern.class); printClassPattern(classLevelPattern, javaClass.getName()); printClassPattern(classLevelPattern, javaClass.getName()); } // Get all design @Pattern declared upon methods via reflection // Get all design @Pattern declared upon methods via reflection Method[] methods = javaClass.getDeclaredMethods(); Method[] methods = javaClass.getDeclaredMethods(); for (Method method : methods) { for (Method method : methods) { method.setAccessible(true); // make private methods accessible method.setAccessible(true); // make private methods accessible Pattern methodPattern = method.getAnnotation(Pattern.class); Pattern methodPattern = method.getAnnotation(Pattern.class); if (methodPattern != null) { if (methodPattern != null) { printMethodPattern(methodPattern, javaClass.getName(), method.getName()); printMethodPattern(methodPattern, javaClass.getName(), method.getName()); } } …code removed for clarity… …code removed for clarity…}

19 Sample HTML Output Design Pattern Usage Java Class: samples.myapp.SampleOne samples.myapp.SampleOne Class level design pattern implemented: Singleton Class Design Pattern, Msg: ‘Singleton Wrapper Class’ Singleton Class Design PatternSingleton Class Design Pattern Java Class: samples.myapp.SampleTwo samples.myapp.SampleTwo Method create() implements design pattern: Factory Method Pattern, Role: 'static factory method' create()Factory Method Patterncreate()Factory Method Pattern

20 Some Ideas on how to apply annotations Things to make you think about how annotations can be used

21 Replace older technology Replace javadoc-oriented precompilers Replace javadoc-oriented precompilers Provide runtime access to metadata - not just compile-time. Provide runtime access to metadata - not just compile-time. Metadata syntax checked by java compiler Metadata syntax checked by java compiler Replace XML-oriented java tools Replace XML-oriented java tools Put metadata in your java files were it is easy to maintain - not in separate XML files Put metadata in your java files were it is easy to maintain - not in separate XML files Do away with verbose, error-prone XML typing Do away with verbose, error-prone XML typing Typically easier to find and fix errors than fiddling with the XML parsing + Java errors Typically easier to find and fix errors than fiddling with the XML parsing + Java errors Provide built-in type checking for metadata via java compiler Provide built-in type checking for metadata via java compiler Rapidly replacing XML usage in J2EE in many areas Rapidly replacing XML usage in J2EE in many areas

22 Application Idea: Binding a pojo to user interface forms @HtmlForm(posturl=“/congo/servlet/saveperson”, resetbutton=false) Public class PersonInfo { @field(name=“pname”, type=FormField.TEXT, size=25, isReqd=true) @format(alignment=Align.LEFT, printf=“%s”) public Sting name; @field(name=“pstate”, type=FormField.RADIO, isReqd=true) @field(name=“pstate”, type=FormField.RADIO, isReqd=true) public State state; @field(name=“page”, type=FormField.TEXT, isReq=false) @format(alignment=Align.RIGHT, printf=“%d”) public Integer age; …}

23 Application ideas: User Input validation @Validator(class=com.fubar.PersValid) public class PersonPojo { @range(min=1, max=115) public int age; @range(min=0, max=20) @default(value=new Integer(0)) @notnull(true) public Integer numberOfDependents; …}

24 Application: EJB Interceptors @Stateless @Interceptors({com.acme.AccountAudit.class, com.acme.Metrics.class, com.acme.CustomSecurity.class}) public class AccountManagementBean implements AccountManagement { public void createAccount(int accountNumber, AccountDetails details) {... }...} public class Metrics { @AroundInvoke public Object profile(InvocationContext inv) throws Exception { long time = System.currentTimeMillis(); try { return inv.proceed(); } finally { long endTime = time - System.currentTimeMillis(); System.out.println(inv.getMethod() + " took " + endTime + “ milliseconds."); }}} public class AccountAudit { @AroundInvoke public Object auditAccountOperation(InvocationContext inv) throws Exception { try { Object result = inv.proceed(); Auditor.audit(inv.getMethod().getName(), inv.getParameters[0]); return result; } catch (Exception ex) { Auditor.auditFailure(ex); throw ex; } }} public class CustomSecurity { @AroundInvoke public Object customSecurity(InvocationContext inv) throws Exception….

25 Application: EJB Security @RolesAllowed(“sysadmin”) public class Maintainence { public void importCompanyData () {...} public void restart () {...}...}@Stateless public class HRActivity { @RolesAllowed(“HR”) public void addToPayroll () {...} @RolesAllowed({“HR”, “Manager”}) public void postJobOpening() {...}...}

26 Application Idea: Code Maintentance Annotations Public class MyAppClass { // Tags to generate documentation of SQL used in your application so it’s easier to // figure out implications of dbms schema changes and dbms tuning. @SqlTracker(preparedQuery=sql) protected static final String sql = “select id, version from astro_entity where type = ?”; public ArrayList getSuperNova(String snType) { ….} // Tags to generate documentation on hacks and things todo for future releases. @Hack(problem=“Uses linear sort algorithm”, fix=“Use tree sort”) @Refactor(idea=“move sorting to separate class”) public void sortSuperNova(ArrayList sn) {…}


Download ppt "Fun with Java Annotations Brian McGinnis. Java Annotations Introduced in “Tiger” release (Java 1.5) Introduced in “Tiger” release (Java 1.5) One of most."

Similar presentations


Ads by Google