I am just looking to write some annotation which can execute at runtime, before or immediately after a service method is invoked.
I don't know if they are executed at runtime or compile time.
Annotations don't execute; they're notes or markers that are read by various tools. Some are read by your compiler, like #Override; others are embedded in the class files and read by tools like Hibernate at runtime. But they don't do anything themselves.
You might be thinking of assertions instead, which can be used to validate pre and post conditions.
Annotations are just markers. They don't execute and do anything.
You can specify different retention policies:
SOURCE: annotation retained only in the source file and is discarded during compilation.
CLASS: annotation stored in the .class file during compilation, not available in the run time.
RUNTIME: annotation stored in the .class file and available in the run time.
More here: http://www.java2s.com/Tutorial/Java/0020__Language/SpecifyingaRetentionPolicy.htm
Actually, when you define an annotation, you must specify the parameter #Retention, which defines whether the annotation is available in the source code (SOURCE), in the class files (CLASS), or at run time (RUNTIME).
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnnotation {}
It depends on retention policy attached with that annotation.
A retention policy determines at what point annotation should be
discarded. Java defined 3 types of retention policies through
java.lang.annotation.RetentionPolicy enumeration. It has SOURCE, CLASS and RUNTIME.
Annotation with retention policy SOURCE will be retained only with
source code, and discarded during compile time.
Annotation with retention policy CLASS will be retained till
compiling the code, and discarded during runtime.
Annotation with retention policy RUNTIME will be available to the
JVM through runtime.
The retention policy will be specified by using java built-in
annotation #Retention, and we have to pass the retention policy
type. The default retention policy type is CLASS.
Annotations don't have effect on your code, they're here to provide information to be evaluated by the compiler or other tools.
Annotations have a number of uses, among them:
Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.
Compiler-time and deployment-time processing — Software tools can process annotation
information to generate code, XML files, and so forth.
Runtime processing — Some annotations are available to be examined at runtime.
See this page.
Annotations are only markers at the source code. They will be used by tools like IDE, compiler or annotation processors.
You can define with #Retention if a annotation should be evaluated in the source, class or runtime.
If you would like define your owned annotations and only you has the knowledge what the annotation should be do, so you should write an annotation processor too.
(but this is not simple - maybe)
They actually can be read in both environments, depending on the retention policy you set.
Related
Can I use java common Annotation like javax.annotation.Resource, javax.annotation.PreDestroy, javax.annotation.security.RolesAllowed in a Servlet class?
Technically, nothing stops you from doing so. You can use that (well, pretty much every other) annotation in any class you want. Of course if the annotation can be applied on that type of Java element (method, field, class). The annotations themselves do not bring any logic or magic in your code. Check the source yourself: you'll see that most of them are nothing but data holders.
Annotations are nothing without processors. The processing can occur at compile time or in a runtime.
Compile time annotation processing can change the source code (simplifying things here) before it is compiled. It can introduce extra behavior, (like null checks) or generate methods (like Lombok's #Getter / #Setter. Compile time annotation are usually removed after processing, they are not present on a runtime.
The annotations you've asked about are different kind - runtime annotations. Obviously, resource injection or role checks cannot be done at compile time. So, they need a processor to take effect too, but that processor must be present on a class-path of a running app. Usually, such processors are provided by an environment you run your application in. In your case, these are Java EE annotation and they require Java EE compatible application server to work. I.e. the magic will happen only if you run your class inside a configured application server, like Glassfish or WebSpere. If you run you application in Tomcat or Jetty (they are web servers) - the annotation won't work, they will be "omitted" because no processors exist to process them.
How does the javac tool process the annotations in the source code? Are they compiled and translated into bytecode or they will be treated in a way that resembles processing the comment lines?
Annotations are handled by the compiler in a special way. They get parsed, but most annotations do not mean anything to the compiler. Some do, for example, if you incorrectly use the #Override annotation, a compile-time error will occur. You can find a list of compiler-relevant annotations here.
After that, the behavior depends on the annotation type:
If an annotation has its rentention policy set to RUNTIME or CLASS, it will actually be included in the class file. If the retention policy is RUNTIME, the annotation can even be accessed at runtime via reflection. Many libraries use this to provide some additional comfort, e.g. JUnit uses #Test to mark methods which implement unit tests and looks for those at runtime.
In addition, the java compiler allows to implement so called 'annotation processors', which can access the AST of the compilation unit and process annotations. This is another proof that the compiler does indeed handle annotations.
Is annotation processing still an active part of Java 6+, or is it something that has been deprecated/discouraged/obsolesced. If obsolesced, why (why is it no longer needed/useful)? And if it's still extremely useful and "active" (a new Java project developing against the Java 6+ JDK would still benefit from it), please confirm/correct my understanding of how annotation processors are used:
You create your own annotation class, say #MyAnnotation
You mark certain classes, methods, fields, etc. with #MyAnnotation
During the build process, you invoke your custom MyAnnotationProcessor (how?)
The processor scans your classpath for instances of #MyAnnotation
Typically, an annotation processor does dynamic bytecode injection, modifying/enhancing your compiled classes on-the-fly
Correct.
Correct.
Correct. Typically you will extend AbstractProcessor. You specify your MyAnnotationProcessor class using the ServiceLoader pattern - this makes it discoverable to the compiler. The Processor Javadoc contains some information on creating this class.
Correct.
This part is not correct. The annotation processor framework does not give you the ability to modify classes. You will need to use some post-compile process to do this as part of your build. What it does allow you to do is create new files. These may be simple resources, new Java source files (that will subsequently be required and eligible to the annotation processor during the same compile), or Java class files. You may also perform custom checks on source code and write errors to the log (causing the compile to fail).
I hope that addresses your understanding questions.
I am trying to understand the retention policy from Java 1.5. But not getting a clear picture.
As per JavaDoc,
CLASS - Annotations are to be recorded in the class file by the
compiler but need not be retained by the VM at run time.
RUNTIME - Annotations are to be recorded in the class file by the
compiler and retained by the VM at run time,so they may be read
reflectively.
SOURCE - Annotations are to be discarded by the compiler
what does it mean by "discarded"?
Is it like the class file will not have the particular annotated element in it by marking it with SOURCE?
SOURCE annotations are only present in the source file.
When the compiler "discards" the annotation, it is essentially ignoring that the annotation even exists. Source annotations basically serve the same purpose as commenting code.
The annotated element is not affected.
#Retention is what you'd call a meta-annotation: it only applies to other annotation interfaces. As such it also only affects the annotation it is applied to.
For example if you had an annotation named #Foo that is itself annotated with #Retention(RetentionPolicy.SOURCE), then the #Foo annotation (on another element) would be parsed by the compiler, but not stored in the resulting .class file (so if you'd ask the runtime if the element had the #Foo annotation, you'd get a negative answer).
This can be useful if you use an annotation purely for documentation purposes or if you want to handle it with annotation processing (during the compile step).
In the Java programming language, annotations can be used as a special form of syntactic metadata in the source code.
Classes, methods, variables, parameters and packages may be annotated. The annotations can be embedded in class files generated by the compiler and may be RETAINED by the Java virtual machine and thus influence the run-time behaviour of an application.
A retention policy determines at what point annotation should be discarded.
Annotation with retention policy RUNTIME will be available to the JVM through runtime.
I have written a java annotation that looks like this:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD) // can I further limit this to only fields of type DomainObject?
public #interface Owns {
}
After briefly looking around I couldn't see if there was a way to further limit the usage of this annotation so that only fields of a specific type could be annotated. This annotation is custom to our domain and can only be used on instances of our base domain object class.
Does anyone know how to enforce this at compile time?
Thanks for any help!
You could emit an error in an annotation processor (you'll have to use a private API if you want Java 5 support). You can use the Messager you get from the ProcessorEnvironment passed to init.
How effective this is might depend on your tool chain. It should be fine if you use javac to compile by the command line or via a build script. In my version of Eclipse, I had to enable annotation processors manually for the project (via project settings) and errors didn't appear anywhere obvious. (The JDT annotation plugins do have extension points that allow better integration with the IDE if you want to provide custom support.) It would pay to check with commonly used tools, especially if you need to support arbitrary development environments.
I believe that this is not enforcable at compile-time - If you want to ensure that it is not on any inappropriate fields, you would have to check at run/load-time.