As I was trying to sharpen my Java skills by creating a Minecraft server plugin, I came across a #EventHandler in a code example for Bukkit plugin development. This is was put just over a method implementation and I was wondering what it is called.
I remember having seen some #Override somewhere else and I want to learn what it is called so I can search it online...
it is Annotation.
Annotations, a form of metadata, provide data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate.
From the doc the usage of annotations are mainly
Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.
Compile-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.
This thing is called an annotation. In Python the counterpart of Java annotations are called decorators.
OK, I will not replicate the link to what an annotation is. Rather, I will talk about how they can operate.
Annotations have both a Target and a Retention; optionally, they can also be #Documented so that you know this annotation has been present at some time in your source code. Now, onto the target and retention since these two "meta-annotations" will definitely have an influence on what you can expect:
the target determines what that annotation can be applied to; this can be a whole class, an instance variable, a method, a... Well, see the doc.
the retention determines how "long" this annotation persists in your source code. The two retention policies used in majority are SOURCE and RUNTIME.
In an annotation such as yours, it is typically an annotation with a runtime retention policy. Such an annotation can be used, at runtime, by specific processing code, to change the behaviour of the target so that its behaviour be controlled by this processing code. Such code is logically called an annotation processor.
Annotations have begun to take quite some an importance in some JSRs:
JSR 330 defines #Inject, #Provider etc as runtime annotations, so that frameworks willing to do dependency injection can rely on these annotations being present; this is the case, for instance, for dependency injection frameworks such as Dagger and Guice (since version 3.0);
JSR 305 defines #Immutable, #ThreadSafe, #NotThreadSafe, #Nullable, #Nonnull with a source retention policy, and #Documented; these annotations can be used by static code analysis tools, and of equal importance, they are typically #Documented as well. Therefore you know what to expect of them.
It is just a annotation.
#Override for ie is used in methods that is overriding method with the same name in the extended "super class"
It's an annotation.
While it usually has no direct effect on code, some object databases may use it to specify the behavior of one or more fields in regard to indexing, keying, or other functions.
Related
I think it's better to start with the idea I want to implement. I'm really inspired by Rust mut pointers so the same type can be immutable and mutable at same time. And I'm thinking is it possible to implement something like this for JVM.
It looks I just need to create annotation #Mutates to annotate methods that changes current class state and annotation #Mutable to annotate local variable, fields and args. Logic of processor is not too hard. For every invocation of method annotated by #Mutates I need to check that corresponding variable/field/arg is annotated by #Mutable. And if method calls any #Mutates method on fields or does assignment (= operator) that method must be annotated by #Mutates as well.
The main problem I don't know where to start as I don't have experience with annotation processing. From my limited understanding I can't use Annotation Processor as it isn't supposed analyze code of methods... So it seems I need to create some compiler plugin (two: for Java and for Kotlin).
Can somebody give me a piece of advice - is it possible at all to do that and how hard is this (so I can estimate efforts and time I will need for that and decide is it worthwhile or not)
The standard annotation processing interface does not provide access to the bodies of methods. However, other frameworks do. For example, the Checker Framework provides an API for annotation processing that descends into method bodies. Building on the Checker Framework, you can create an annotation processor that enforces your mutability rules at compile time: the annotation processor would halt compilation with a javac error message if a rule is violated.
Dozens of annotation processors have been built on the Checker Framework, and it is used daily at Amazon, Facebook, Google, Uber, etc.
Disclaimer: I am one of the maintainers of the project.
I have a simple annotation processor which is applied like this:
#DiffElement(diffReceiver = Renderer.class)
class ViewState {
String getHello();
int getWorld();
}
class Renderer {
void renderHello(String hello);
void renderWorld(int world);
}
For this processor to work, name of get-functions and Renderer-interface function arguments must match. It checks this and it uses annotation's argument to look at the provided class and do some code generation based on that.
It generates one file.
I have read the docs on Incremental annotation processing and I can't decide which category to apply to this processor. Here are my considerations:
it can't be isolating, because it doesn't derive everything from annotated element's AST, as it also inspects a class from annotation argument
it can't be aggregating, because it doesn't have any annotation on Renderer class, so according to the above documentation, processor won't be called whenever Renderer class changes, because processor hasn't registered to process this file, so this will lead to errors in generated result.
Questions:
Do I understand documentation correctly? Or can some category still be applied to this processor
If it doesn't fall in either category, how can I tell Gradle that it is not incremental, so tools like "kotlin kapt" won't complain to the user that my processor is not incremental
Do I understand documentation correctly? Or can some category still be applied to this processor
Documentation on processor categories is really short and, in my opinion, lacks examples. I spent a lot of time figuring out these docs building some simple projects for experiments. So, as far as I know, a category can be applied, if I did figure them out correctly in the end :)
You say that
it can't be isolating, because it doesn't derive everything from annotated element's AST, as it also inspects a class from annotation argument
This is not exactly right and I'll explain why.
As mentioned in documentation, isolating processors
must make all decisions (code generation, validation messages) for an annotated type based on information reachable from its AST. This means you can analyze the types' super-class, method return types, annotations etc., even transitively.
"Even transitively" phrase is very important here - it means, that you can analyse not only annotated type's AST, but, for example, some of it's method's return type's AST as well, and then, let's say, a superclass of that type...
As I understand it, every type, that you can discover via AST walks from the annotated element, is a dependency of the annotated type (or element in general). And if a dependency is changed, then the depending type needs recompilation. So when Renderer class changes, ViewState will be recompiled and thus reprocessed, because it references Renderer as its annotation argument. Supertypes, superinterfaces, methods' return types, method parameters' types, annotation class arguments, ... - all these are considered dependent types.
So, your annotation processor actually can be isolating.
P.S. If isolating doesn't work, ensure that annotation retention is CLASS or higher, for whatever reason.
P.P.S. I find incrementality in annotation processing a really shady topic, full of surprises and underwater rocks. The rule of thumb I discovered for myself is that practically every processor with a few tweaks can be isolating, unless it really needs to generate one entity based on many inputs. And, what's important, only if these inputs can be completely unrelated to each other in terms of references or even be in a different libraries.
it can't be aggregating, because it doesn't have any annotation on Renderer class, so according to the above documentation, processor won't be called whenever Renderer class changes, because processor hasn't registered to process this file, so this will lead to errors in generated result.
This isn't going to be a direct answer, but I think it may still answer your question: This statement, as I understand it, is the actual source of your problem. Any mildly incremental system is going to fail you here, not just Gradle's "aggregating" mode (try using your processor in a simple Eclipse project, for example, and possibly even IntelliJ, though I've had mixed results there).
If you actually want to enforce that changes to an un-annotated type will cause your annotation processor to run again, you must not limit your annotation processor to that annotation, but must return the magic "*" value from getSupportedAnnotationTypes(), indicating that any changed class must trigger the processor to re-run. From the Javadoc for this method:
Finally, "*" by itself represents the set of all annotation types, including the empty set. Note that a processor should not claim "*" unless it is actually processing all files; claiming unnecessary annotations may cause a performance slowdown in some environments.
Ideally, you would just make a second (or third, etc) annotation to provide this hint instead, but that isn't always feasible, which is why you're allowed this wildcard option
I want to know, if I've got it correct or not. I've been reading about annotations and wanted to know how all the magic happened. Here's what I think happens. Please let know if otherwise.
Firstly, let's take some annotation. Say AssertTrue. Now, the specs of the annotation is provided in javax.validation.constraints. Now, as such, AssertTrue does not really do anything. i.e. if I were to do the following
public class MyClass{
#AssertTrue(message = "MyMessage")
public myMethod(){
//something
}
}
Now, this particular piece of code is not going to do anything but save the metadata info that on this method myMethod I have some additional info i.e. message and annotation. How I make use of this info is upto me.
This is where the hibernate-validator framework comes into picture.
What it does is, that it provides a bunch of classes and it takes in the object that is supposed to be validated. On that object, it will check if AssertTrue annotation is there. If found, it will invoke the method isValid that is provided in the implementation of the AssertTrueImpl.
Is this what is happening?
Also, I have a few questions. say I have my own custom annotation and I want to provide a framework that checks something. For the sake of argument, let's say I want to do what the hibernate-validator is doing. Now how does one go about it?
Also, when the JVM encounters some annotation, what happens behind the scene? Does it look for some implementation? What exactly does it look for?
i.e. what will JVM do if it encountered AssertTrue in my code. Surely it does not have to do much but store some information, and it does not have to go looking for any implementation too, since whenever I call validator.validate() that's when it will look for hibernate-validator implementation.
let me know if I have understood it correctly.
You are correct. The annotation by itself does nothing, it's just metadata that may be used by a processing tool. In this case, Hibernate validator.
The usual procedure for those tools is to scan on the classpath what classes have metadata that they can use to build or enhance a class (by injecting a proxy, or registering an interceptor, or any other kind of operation). They either do scan the classpath, or an external configuration mechanism (xml, json, annotations on a config class [Spring way]) specifies this for the framework so that it knows where to look for annotated classes.
And so, you too, can benefit from annotations on your project, following the same discovery method. In fact, if you happen to work with CDI, you will probably use them a lot. They're quite useful for bean interception, or for providing metadata on your classes that would otherwise have to be treated with a lot of boilerplate code.
I encourage you to use them profusely.
Cheers!
You understand annotations correctly - they are just metadata on specific members (fields, methods, classes, ...). Some of them are intended for compile time only, some of them are intended for runtime. The latter will be available via Reflection API (basically forming additional metadata on annotated members). There are numerous possibilities of what you can do with this feature, where declarative validation defined by JSR-303 (and implemented by Hibernate Validator) is just one of them.
I've been reading about annotations lately, and I'm a bit confused. I've used the annotation #NotNull but I don't really know how it checks if the variable is not null. No where in the code do I see anything checking values for null. That makes sense because it's an interface, so where does the actual processing happen and why isn't this location specified in the code? The examples I've seen usually just make an annotation that takes values, but doesn't do anything else, so I'm confused as to where the implementation occurs.
Annotation is just a metadata, no more no less.
When you want to specify some details about the class you put annotations on it.
Think about them (to some extent) as an alternative to the old well known XML way to define metadata.
Now, its obvious that someone reads your XML and runs the code that makes something with the metadata. The same happens with annotations: a framework to which annotation belongs to is responsible to read the annotation and make something with this information. In the case of #NotNull, its hibernate-validator project. The API exposed by java allows to access the information in the annotations by reflection (the classes like java.lang.Class, Method, Field, and so on). So somewhere inside hibernate validator there is a code that goes to your class, reads the annotations by reflection and checks whether the class adheres these annotations.
These annotation usually have retention policy 'runtime' which means that they're preserved in the bytecode and loaded along with the class that carries these annotations.
There are also annotations that should be processed by Java compiler. Like #Deprecated, #SuppressWarnings and so on. The benefit of having such annotation is that you can find some code issues during the compilation phase.
You can also put the annotation processors and 'plug' them during the compilation phase, buts its entirely different story.
Hope this clarifies a little the usage of annotations
i want to ask why are the java annotations used so much... I know that they replaced xml configuration in for example jpa, but why is this kind configuration used at all?
Consider this piece of code:
#Entity
class Ent{
// some fields
}
//... somewhere in the other file far far away
class NonEnt{
// whatever here
}
Now, when I try to put this in persistence context, with EntityManager's persist method, I get runtime error(better would be to get compile error) with trying to persist NonEnt instance. There is obvious solution for me, force the entities to implement some no-method interface instead of using #Annotations. But this isn't popular among framework designer, what is the drawback of this solution?
Thanks for answering...
When compared to marker interfaces, annotations have some advantages:
they can be parameterized
they are more fine grained - you can attach them not only to classes but also to other class elements (fields, methods, method arguments, etc)
Annotations are also supposedly less intrusive, but this point is matter of taste and debatable.
See also:
Annotations (official JDK documentation)
What is the use of marker interfaces in Java?
The use of annotations is a lot less invasive than forcing the client to implement a interface or extend a class.
There is obvious solution for me,
What you describe is called a "marker interface" and it's an abuse of the interface concept. I suspect the only reason why you consider it obvious is because of Serializable - which only exists because there were no annotations at that time.
force the entities to implement some
no-method interface instead of using
#Annotations. But this isn't popular
among framework designer, what is the
drawback of this solution?
What are its advantages? Annotations have the huge advantage that they can have parameters, and they are much more fine-grained. Marker interfaces only work at the class level.
Citing the java tutorial:
Annotations provide data about a
program that is not part of the
program itself. They have no direct
effect on the operation of the code
they annotate.
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.
As you can see, annotations are a way of specifying meta-data about your types in java, including interfaces, they are in no way a replacement for them.
Java annotation are really helpful when you want to add some additional information to your class, method or instance variable. There are a lot of libraries which use these annotations heavily. These annotations keep the code simple and readable with the power of making changes to the code at runtime.
For example if you have used lombok library, which creates setter, getter and constructor at compile time and saves you lines of code and time.
When compiler executes the code, lomok searches for all the fields marked with #Setter or #Getter annotation and add setter and getter for that field in the class.
One other example is Junit test runner. How junit differentiates between normal helper method in test class and a test. To differentiate between the two it uses #Test annotation.
This tutorial explains how you can use java annotations to create you own test runner.