I'm trying to understand the use of 'Annotations' a bit better.
I understand that:
How to access annotations in my code for example via this complete tutorial.
I can create methods to perform desired operations
To understand this better, I created a virtual problem as following:
There are Annotations TestAnnotation1, TestAnnotation2, TestAnnotation3(definition is available latter in the question). I wants to execute the methods of class MethodsExecutorClass as following:
When TestClass.java compiles then execute CommonMethod() and RetentionPolicySOURCEMethod()
When TestClass.class loads then execute CommonMethod() and RetentionPolicyCLASSMethod()
Whenever testMethod() method of TestClass.java executes then execute CommonMethod() and RetentionPolicyRUNTIMEMethod()
By this example I wants to understand following:
Can I instruct Java compiler (javac) or Java Runtime Environment (jvm) to execute a method in my class(e.g. CommonMethod()andRetentionPolicySOURCEMethod()methods ofMethodsExecutorClass`).
Can I delegate the monitoring (i.e. searching the methods/classes which are using my annotation etc.) to any other entity(which is available in Java SE).
I want to do something like #Override and #deprecated annotations. We don't do something extra. Although on Oracle javadoc site, here it is clearly mentioned that The Java platform has always had various ad hoc annotation mechanisms. and #deprecated is one of them. But I wondered If I can do something like this.
Definitions should look like as following:
MyAnnotations.java:
#Retention(RetentionPolicy.SOURCE)
public #interface TestAnnotation1
{
String className();
}
#Retention(RetentionPolicy.CLASS)
public #interface TestAnnotation2
{
String className();
}
#Retention(RetentionPolicy.RUNTIME)
public #interface TestAnnotation3
{
String className();
String methodName();
}
MethodsExecutorClass.java:
class MethodsExecutorClass
{
public static void CommonMethod()
{
System.out.println("In method: CommonMethod()");
}
public void RetentionPolicySOURCEMethod()
{
System.out.println("In method: RetentionPolicySOURCEMethod()");
//Also print annotation arguments e.g. Class name etc
}
public void RetentionPolicyCLASSMethod()
{
System.out.println("In method: RetentionPolicyCLASSMethod()");
//Also print annotation arguments e.g. Class name etc
}
public void RetentionPolicyRUNTIMEMethod()
{
System.out.println("In method: RetentionPolicyRUNTIMEMethod()");
//Also print annotation arguments e.g. Class name etc
}
}
TestClass.java:
#TestAnnotation1(TestClass.class)
#TestAnnotation2(TestClass.class)
class TestClass
{
#TestAnnotation2(TestClass.class, "testMethod()")
public void testMethod()
{
System.out.println("In method: testMethod()");
}
}
May you help me in achieving this? (Please no guess or assumptions, but presumptions would be also helpful).
I'm not sure if this can be achieve, but looking forward.
Annotations with retention policy RetentionPolicy.SOURCE are only available during compilation time of the code so your compiler should support your annotation to use it, otherwise it's not possible to handle the annotation. Usually, such annotations are used to detect possible problems at compilation time, for example, annotation #Override. That's why your first problem can't be implemented in usual ways.
Annotations with retention policy RetentionPolicy.CLASS are available only in .class files and can be used via JVMs. Please see this answer how it can be used. The second your problem also can't be implemented via standard ways.
Commonly used annotations are with retention policy RetentionPolicy.RUNTIME that are available via reflection mechanism in Java. But to solve your third problem you have to use some method invocation interceptors, for example, via Aspect Oriented Programming. After that you can get method's annotations via method.getDeclaredAnnotations().
Can I instruct Java compiler (javac) or Java Runtime Environment (jvm)
to execute a method in my class(e.g.
CommonMethod()andRetentionPolicySOURCEMethod()methods
ofMethodsExecutorClass`).
No, you can't.
Can I delegate the monitoring (i.e. searching the methods/classes
which are using my annotation etc.) to any other entity(which is
available in Java SE).
You can do it via AOP, for example, use the library AspectJ.
Related
I am trying to write a code for custom annotation. when I use this annotation on any method, then before execution and after execution of method some simple print msg should execute. I tried like this :
import java.lang.annotation.*;
#Retention(RetentionPolicy.RUNTIME)
#interface DemoAnnotation {
String value();
String value1();
}
// Applying annotation
class CustomAnnotationExample {
#DemoAnnotation(value = "code is started!!!", value1= "code is completed!!!")
public void sayHello() {
System.out.println("hello Annotation Example");
}
}
and in another main method I called it like :
CustomAnnotationExample h=new CustomAnnotationExample();
Method m=h.getClass().getMethod("sayHello");
DemoAnnotation anno=m.getAnnotation(DemoAnnotation.class);
System.out.println(anno.value());
h.sayHello();
System.out.println(anno.value1());
I want to print values from annotation without using System.out.println() in main method . when I just call sayHello() method . annotation values should get printed before and after execution of sayHello() method.
Please help me on this.
There are two ways, both of them very complex, runtime and compile time solution:
The runtime solution relies on specific framework which is used to instantiate the application. The common way is to create wrapping proxies for the final object and do the stuff from the proxy before (or after) calling the original object method.
For spring for example the solution is to register BeanPostProcessor object which would intercept the instantiation of the bean and check whether some of the method contains the DemoAnnotation annotation. In case it does, it would create a proxy to that object and return the proxy as the real bean.
Second solution is compile time solution and is based on annotation processors which can modify the java compiler behavior. You need to create and register annotation processor and after parsing the source file checking the annotations on the method and add the relevant code during the compilation time. There are many helpers, you can for example register on TreeScanner.visitMethod() method and invoke the TreeScanner from your annotation processor.
Generally the good example can be found in lombok which does similar things in terms of modifying the code during the compile time.
I am writing a library, so I don't often use the methods in my classes within the same project. As such, my IDE (IntelliJ IDEA) keeps warning me that the methods are unused.
Of course, the obvious solution is to place #SuppressWarnings("unused") before the classes. I don't like this; it doesn't describe the reason I'm writing that annotation and is very verbose. I would love to make an annotation like #LibraryClass which is just an alias of #SuppressWarnings("unused").
In short, I want to be able to change this:
#SuppressWarnings("unused")
public class MyLibraryClass {
public void myLibraryMethod() {
doSomething();
}
}
to this:
#LibraryClass
public class MyLibraryClass {
public void myLibraryMethod() {
doSomething();
}
}
but I have no idea how to do this! I tried all this, and it compiles, but the IDE still warns of unused methods:
#SuppressWarnings("unused")
#Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
#Retention(RetentionPolicy.SOURCE)
public #interface Library {
SuppressWarnings superAnnotation() default #SuppressWarnings("unused");
String[] value() default {"unused"};
}
To do one aspect of what you're asking for - attaching some kind of compile-time logic to annotations - you need to look into annotation processing. An annotation processor hooks into the Java runtime, like an agent, and gets informed about annotations and given an option to process it. To use that, you'd have to put your annotation-processor jar on the IDE's classpath.
Some links:
http://hannesdorfmann.com/annotation-processing/annotationprocessing101
http://programmaticallyspeaking.com/playing-with-java-annotation-processing.html
However, that wouldn't allow you to change the way that Intellij detects unused methods, which seems to be closer to your specific use case. What you could do there is to modify the Intellij 'unused method' inspection so that it incorporates a check for the custom annotation you've defined. YMMV, I've never had to do that at the class level before.
https://gist.github.com/itzg/5e90609cde1473ef9d4d
When I call fooMethod, I want to process first class annotation (with First.class - in my project this checks if user is logged) and then method annotation (with Second.class - in my project this checks if uses has desired rights to access this specific method. So I need to ensure user is logged first). Is there a way to do that?
#With(First.class)
public class Foo{
#With(Second.class)
public static void fooMethod(){
}
}
Also I wonder why custum action ignores annotation. Code below doesn't process anotation #With(First.class).
public class Foo2 extends Action<CustomAnnotation> {
#Override
#With(First.class)
public Promise<Result> call(Http.Context context) throws Throwable {
return delegate.call(context);
}
}
}
Similar unanswered question: Java + Play Framework 2 with nested action compositions in the same class
In Play 2.4 there appears to be an option for this from the docs here:
Note: If you want the action composition annotation(s) put on a
Controller class to be executed before the one(s) put on action
methods set play.http.actionComposition.controllerAnnotationsFirst =
true in application.conf. However, be aware that if you use a third
party module in your project it may rely on a certain execution order
of its annotations.
The note is only present in the 2.4 docs, so presumably it doesn't work in previous versions.
It looks like at least in Java 8 you have an order in annotation of the same kind: Java Annotations Reflection Ordering.
I'm trying to create an annotation for a local variable. I know that I can't retain the annotation in the generated bytecode, but I should be able to have access to the information at compile time by doing something like this:
#Target({ElementType.LOCAL_VARIABLE})
#Retention(RetentionPolicy.SOURCE)
public #interface Junk {
String value();
}
only, this doesn't get processed by apt, or javac when I specify a ProcessorFactory that has "Junk" in it's supported types in the following:
class JunkTester {
public static void main(String[] args) {
#Junk String tmp = "Hello World";
System.out.println(tmp);
}
}
It will however work when I move the #Junk annotation before public static
Thoughts and or workarounds?
Did some quick tests and searched a little, and it's looking like hooking into LOCAL_VARIABLE isn't really supported...yet:
http://forums.sun.com/thread.jspa?threadID=775449
http://www.cs.rice.edu/~mgricken/research/laptjavac/
https://checkerframework.org/jsr308/
Could be totally wrong, but that's how it's looking...
It seems that the Type Annotations Specification (JSR 308), will hopefully address this subject in the future (JDK 8 ?).
As of Java 8, local variable annotations are stored in the classfile.
A standard Java annotation processor does not process the bodies of methods.
However, the Checker Framework enables you to write an annotation processor that processes every annotation including on local variables. Its annotation processors can even examine every statement of the program, whether annotated or not.
do they by annotation mean a comment in a code with // or /* */?
No, an annotation is not a comment. An annotation is added to a field, class or method, using the syntax #Annotation. One of the best known annotations is #Override, used to signal a method is overriding one from a super class. For example:
public class MyClass {
#Override
public boolean equals(Object other) {
//...
}
}
See http://download.oracle.com/javase/1,5.0/docs/guide/language/annotations.html for more info.
No, annotations take the form:
#Annotation(property="A")
public class {
#Annotation(property="B")
Object field;
#Annotation(property="C")
public void method() {
}
}
Annotations can be placed on classes, methods or fields. They can provide information at runtime via reflection or compile time via apt (short for Annotation Processing Tool and not the apt package manager).
They are defined as:
#interface Annotation {
String property();
}
See http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html for more
Actually, before Java5 (i.e. 1.3 or 1.4), comments (// or /* */) were the only way to add annotation (i.e. "metadata") to be acted upon.
One classic example is the way the unit-testing framework TestNg propose all its Java5 #Annotations as comments if you are using TestNg with Java 1.4.
But that means, for Testng to launch the proper test suite, it had to access the sources of your program, not just the compiled binary.
Unlike Javadoc tags, Java annotations can be reflective in that they can be embedded in class files generated by the compiler and may be retained by the Java VM to be made retrievable at run-time.
No.
An annotation is a special construct introduced with java 1.5. An annotation adds some meta information to a java class, method or variable. This meta information can be evaluated at compile time (e.g. for generating some extra code with apt) or at runtime (e.g. to match a class to a database table).
Example for a built in annotation:
#Deprecated // this is an annotation
public void myMethod() {
...
}
Annotations are not just for java they also exist in c++, they are somehow similar with those from java.
// MyCode.h
# include <CodeAnalysis/SourceAnnotations.h>
using namespace vc_attributes;
class CMyClass
{
public:
void f ( [Pre ( Valid = Yes )] int *pWidth );
// code ...
};
// MyCode.cpp
#include "MyCode.h"
void CMyClass::f ( [Pre (Valid = Yes)] int pWidth )
{
}
You can check the MSDN for more information:
http://msdn.microsoft.com/en-us/library/ms182036(VS.80).aspx
An annotation is not a comment but it is used for many purposes such as error debugging as well it is the instruction set to the compiler but it hasn't any effect on the runtime code.
#override,#deprecated and others are the examples of annotation. It can be used with methods,constructors,parameters,variables.
Annotations are used to give detailed information to the compiler whereas Comments are for the convenience of the programmer so that he know how the code is structured.
of course not, but I think annotation ≈ comment.
the core of them is describe, but annotation has more confinement, you are not easy to make mistak, also, you can find mistake in compile time.