Hi : I wanted to make sure that an annotation is present at compile time in a class. Is this possible ? I realize that annoataions are, themselves, classes, so I assume so - but Im just not sure syntactically where and how to enforce/implement such a structure in my classes.
You can write an annotation processor to run arbitrary logic at compile time.
From an annotation processor, you can do things like check whether a class has a particular structure or member present if a particular annotation exists on that class. They are pretty flexible - for more of an idea of what you can do with them check out the API. They are also supported in major IDEs such as Eclipse and Netbeans.
An introduction to writing an annotation processor is here (link dead, partial copy here).
Related
I was browsing the source code of the Lombok project, as I'm learning about Annotations and AOP in general and I thought that would be a good example to draw inspiration from.
However, I don't understand, the AllArgsConstructor only defines the annotation - that part I get from what I grasped so far - but where is the code that actually adds the constructor ? And all other annotations.
Let me first note that if you want to learn about annotation processing, Lombok is not a good example to start with. Lombok is not a regular annotation processor (which only adds new source files to the compilation). Instead, it modifies existing Java sources. That is not what annotation processors typically do, and it's not something the annotation processing in javac was designed for. Lombok uses the API of javac to modify and enrich an abstract syntax tree. That makes it complex and difficult to understand.
To answer your question, the logic that generates the code for Lombok annotations is located in so-called handlers. In your case, it's the HandleConstructor classes (there are two of them: one for javac, one for the Eclipse compiler).
Is there a way to modify .class files in order to add Java annotations to certain methods? Basically I want to traverse methods of each class file in a jar file and annotate certain ones. Note that this is not at run-time while using the jar file. Rather, after I'm done I want to have modified class files with the annotations.
I do have access to the source code, so if there's an automatic source code modifier, that would work as well...
I'm assuming I'll need a tool such as Javassist or ASM. If so, which one should I use and how would I go about it?
Actually, this is a classic use case for AspectJ:
declare #method : public * BankAccount+.*(..) : #Secured(role="supervisor")
While I will grant you that direct byte code manipulation is more powerful, AspectJ is much more user-friendly, and it immediately gives you compiler warnings when you are doing something wrong.
Also, if you use Load Time Weaving, you can leave the original library jar unchanged, because the weaving happens at class-load time.
Reference:
Declare Annotation
AspectJ in Action (book)
Googling for an hour or so turned this article up which seems to completely answer my question: use ASM. To write class files using the changed bytecode, use ClassWriter.
Well, time to get to work then, I guess. :)
We are migrating a system written in C to Java and must retain existing processes (no debate). We currently "embed" compile-time information into the C application using the C preprocessor, for example:
cc -o xxx.o -DCOMP_ARG='"compile time arg"' xxx.c
The xxx.c file can then use "COMP_ARG" and its value will be embedded in the code and we have little worry about it being changed inadvertently.
We realize Java likes to use properties files, however, our requirements are such that some information ** ** be embedded in the code, so properties files are not an option - these certain values cannot be specified at runtime. To illustrate the point, such data could be a date-stamp of when the file was compiled, but the exact data is irrelevant to the question.
We are looking for a way to specify at compile time various values that are available to the Java code. We are quite aware that Java does not have a pre-processor as does C, so the mechanism would be different.
Our current solution is using a code generation step (Maven), which does work, however, Eclipse is wreaking havoc trying to deal with the source files so that we had turn off "Build Automatically". We really want to find a more robust solution.
We appreciate any help, thanks.
The xxx.c file can then use "COMP_ARG" and its value will be embedded
in the code and we have little worry about it being changed
inadvertently.
...our requirements are such that some information be embedded in the
code....
We are looking for a way to specify at compile time various values
that are available to the Java code. We are quite aware that Java does
not have a pre-processor as does C, so the mechanism would be
different.
It seems that the best way to solve this problem would be to make use of annotations in your code.
In Java, annotations are a kind of interface declaration, but they do not enforce a behavioral contract with an implementing class. Rather, they are meant to define a contract with some external framework, preprocessor, or with the compiler itself. Annotations are used extensively in Java EE 5.0 (and later) to specify configuration and behavior to the framework within which the developer's code runs. Annotations are also used extensively by the JavaDoc documentation processor. Here, the annotations in the doc comments allow you to specify and format the information which you intend to appear in the documentation when the JavaDoc processor runs.
Annotations can be defined to be accessible at runtime. In such a case, the primary mechanism for accessing annotations is the Java Reflection facility. For example, annotations with a retention policy of RUNTIME and defined on a class, can be accessed through that class's corresponding Class object:
Class myCls = MyClass.class; // the "class literal" for MyClass
Annotation[] annotations = myCls.getDeclaredAnnotations();
Annotations can include arguments for parameters to allow for more flexibility in configuration. The use of annotations is most convenient when the code itself can be so annotated.
A quick tutorial on how annotations are defined and used in Java is available here: https://docs.oracle.com/javase/tutorial/java/annotations/
I'm going to post my own answer which seems to be "Can't be done" - what can't be done, apparently, is provide at compile time to Java, a set of parameters that gets passed to the program at execution time. The solution appears to be to continue with what I am doing which is to update a Java source file with the compile-time data and figure out how to coax Eclipse to stop over-writing the files.
Thanks to everyone who commented.
Even after spending a good time, I am unable to understand the purpose of Annotation Processing.
I understand why annotations are required for run-time, simplest example I can think are:
Replacement of marker interface.
Replacement of market properties of a type (e.g. transient)
In general, any usefulness that can be done at runtime.
But unfortunately, i could not understand any practical example/reason of using annotation at compile time(except for default annotations provided by JDK e.g. #Override, etc).
I could not understand what is the purpose/need of 'generating code' using Annotation Processors.
Edit: Javadoc/Custom Java doc is one utility I can think of as a purpose of using annotation processors.
This can be used for all sorts of things.
Two simple examples
The Lombock project. Tired of writing thousands of getters and setters? Why not let an annotation processor do it at compile time.
AOP. You can use something like AspectJ to weave in code dependent on annotations. This would be done post compile but as part of the compilation process. For example Spring AOP uses the #Transactional annotation in combination with AspectJ to weave transaction code around methods marked with the annotation.
There are many other uses, but they generally break down into two categories
To reduce boiler plate code.
For cross-cutting concerns.
There are two main purposes of the annotation processing environment - analysis and code generation.
The analysis permits you to extend the capabilities of the java compiler, analyzing program elements as they are being compiled, possibly adding additional constraints, validations, and reporting errors and warnings for violations of those constraints.
Code generation permits you to generate additional supplementary code from signals in your existing hand-written code, primarily (though not exclusively) keyed off of Annotations.
Some examples include Dagger, which is a system for compile-time-analyzed dependency injection, reporting errors and warnings normally found at runtime instead during the compilation of the code. Dagger also generates all the code that would normally be done with reflection, or by hand-writing glue-code, providing substantial performance benefits (in some cases) as well as infrastructure code which is available for step-through debugging, etc.
Another example is the Checker Framework which evaluates a variety of checks against your code, including null safety, etc.
A third example is Auto-Value intended to make small value types nearly trivial to write.
One thing the annotation processing environment is decidedly not suited for is mutation of existing code in place, or modification of code currently under compilation. While some projects do this, they are not actually using the annotation processor APIs but casting to internal compiler types to do so. While this is clearly possible, it's potentially brittle, and may not work reliably from version to version, or compiler to compiler, requiring custom handling for each version and compiler vendor.
I'm trying to identify places where annotation names are the same or similar to compile a list of these things to make sure our team knows where possible points of confusion can be found. For example, Guice #provides and RESTeasy #provider are similar enough in spelling but different enough in semantics as to confuse people so I'd like to call that out explicitly and explain the differences.
What I'm looking for is a tool or even a website that enumerates the annotations associated with packages. This might be a pipe dream, but before I manually start going through and collecting these things I thought I'd check.
I was considering writing one based on Javadoc that simply only pulled in the annotations but I don't have access to Java source files in many cases.
Any thoughts or suggestions?
In Eclipse you can use the standard method "Search for references" (context menu of a used annotation References -> Project) and you are getting a list where the annotations is used within your project.
I suggest to scan for annotations yourself and generate a list for that.
You can do that by writing your own implementation of an annotation processer, i.e. extend AbstractProcessor. Within this processor you can write a text file containing all Annotations. You can add this processor to your build procedure, then it will execute the processor when you build the project.
Another way to do this is using the Google Reflections library. This might be a bit more work since you would need to write a small programm to fetch the annotations and write the file.
I wrote such a tool: https://github.com/MoserMichael/ls-annotations
it decompiles the byte code and lists declarations (classes, functions, variables) with annotations only. You can also use it to find all classes/interfaces derived from a given class/inerface - and all the classes/interfaces derived from a given class/interface.
The tool uses the asm library to scan class files and to extract annotations. it can detect annotations with retention policy CLASS and RUNTIME. It can't detect annotations with retention policy SOURCE that are not put into bytecode, for example #Override is one of these.
Why not scanning your classpath and export all used annotations? Then just use some simple parsing / text compare to see the elements with almost the same name?