I've implemented some custom runtime method annotation. Now I want to check (preferably in compile-time) that all methods which were marked with my newly implemented annotation are static and have only one serializable argument. How can I archive it in Java 7?
You can use annotation processing to do that. Run javac with proc, processor and processorpath option and implement a Processor that does all the checking you want.
Note that you can't enforce others to use these options, so you should still include appropriate runtime checking.
Related
I'm a bit new to annotations in Java. Is it possible to design a custom annotation which when used in a class automatically invokes a method present inside another Class. TIA.
The answer is "sort of": annotations by themselves do nothing (except "compile time" annotations that affect the compile process).
Meaning: just attaching an annotation to something doesn't magically cause a method to be called at some arbitrary point in time.
This works differently: you have some sort of framework - and at some point you ask the framework to process an object, class, ... And then the framework might check for the presence of certain annotations to "do" something based on that check.
Thus: it is possible to implement custom annotations, and it is also possible to make some "framework" react to the presence of that annotation.
In case you find this answer too generic - well, it can't be more precise/specific than the question ...
Is it possible to write a Java annotation for a class that generates a method that overrides the class's parent method?
In my case I want to do it in android:
#OverrideOnTouch
class Foo extends Activity {
And it will generate an onTouch override method in compile time.
Is it possible?
An annotation cannot generate code.
You could write an annotation processor that added a method at compile time wherever it found your annotation.
Here is a tutorial on this subject:
Annotation Processing 101.
However, beware that writing an annotation processor is a significant amount of Java coding work. Also note that an annotation processor (implemented using the AnnotationProcessor API and called via the Java compiler) cannot modify Java source code. It can only generate new ".java" files.
So, if you want to inject new method into an existing class, you would need to compile the class, and then use a post-compilation annotation processor that used BCEL or equivalent to add the required methods to the ".class" files produced by the compiler. Implementing a BCEL-based processor is ... even harder. And such processors have a tendency to break when you upgrade Java. (It is easy to make assumptions about the JVM / bytecode level implementation that are not supported by the relevant specs ... and no longer "work" when the platform changes.)
This approach is mentioned in some of the answers to this Question:
How to write a Java annotation processor?
What I have known are:
annotation was added in java 5
annotation can be using in method, class, and property
annotation can work in RUNTIME, CLASS, SOURCE( I don't know how to work with CLASS and SOURCE, and their's features)
annotation with retention which is RUNTIME can be implement when java program is running.
And I want to implement a annotation to have follows features:
ensure class only being allowed to create a instance
ensure methods only being allowed to access method in the class
it is like as friend in c++
it is same as public and private , but more dynamicall, like
#MyAnnotation(allowMethods={xxx.doSomething})
public void getValue(){}
the getValues method only can be accessed in the instance self and xxx.doSomething() method
What should I do and learn in next?
And Where can I learn about these?
I think you might be misunderstanding something there. Annotations are descriptive elements, not parts of your program. You can write as many annotations as you want, and people who use your code will still be able to ignore them.
That said, an annotation that enforces a policy (as yours does) can actually be implemented, either at compile or at runtime, but you need an external mechanism to help you. I can think of 3:
Annotation processing lets you interact with the compiler and process annotations by generating code or by omitting compiler errors. Unfortunately, I don't think it will work for your case, as you want to protect your annotated type from instantiation, and that means the call site doesn't actually have an annotation. Annotation processing only gives you access to the actual code pieces that have annotations, not to those that refer to them.
AspectJ allows you to write policy enforcement aspects and omit compiler errors, based on static pointcuts. The problem here is that static pointcuts have very limited semantics, so while you could forbid the instantiation of your class altogether, or from certain packages, you could not limit the your class instantiations to 1.
The third way, and probably the only sane way is that you use a container like Spring or Guice and configure your class as singleton. As long as you only retrieve your class from the container, it will never create a second instance.
Finally: If you want to limit the number of instantiations of your class, you can always use a classic Singleton pattern approach.
I am not really sure about Java Annotations, but I think they can solve my problem.
I have an java interface "Target". This is an empty interface, so I can give that implementation into an "TargetHolder", which is simply a list of Targets.
Now I only have 2 Types of Targets. Type "Alpha" and type "Beta".
Type "Alpha" has no functionality in common with Type "Beta".
Easiest way would be to just extend "Beta" and "Alpha" from "Target". But with this solution it is possible for a programmer to create a class that extends "Target" only, which must not be possible.
Can I solve that with annotations?
How?
In theory you might be able to implement the checks (at compile time) using an annotation processor. The problem is that javac will only run an annotation processor on a source file if it finds the right kind annotation in the source.
"After scanning the source files and classes on the command line to determine what annotations are present, the compiler queries the processors to determine what annotations they process. When a match is found, the processor will be invoked."
(Javac manual)
But it seems like you want an annotation on an interface to constrain all classes that implement that interface. That means checking all such classes ... but I can't see how you could trigger the running of an annotation processor on a class that has no relevant annotations.
That leaves you with a couple of options:
Implement the checking as (say) a PMD rule.
Write a tool to find the relevant interfaces at runtime, retrieve their annotations, then trawl for all classes that implement the annotated interfaces.
My advice would be to put this into the "too hard" basket. It is probably going to take more time to implement this than you would save in picking up related coding errors earlier. (I'm thinking that the case that you are trying to avoid will be picked up when someone tries to use class. So, you (or your client) should find your (their) incorrect class in testing ...)
How about?
Create a package just for this work. Let us call it target.
Put Target.java in package target - package private.
Put Alpha.java in package target - public
Put Beta.java in package target - public
Compile, jar, and seal package target.
Using Tool like JArchitect allows to enforce design rules.
In your case you can use the following cqlinq query:
warnif count > 0 from t in Types where t.Implement ("Target")
&& (!t.Implement("Alpha")|| !t.Implement("Beta"))
select t
I have created an annotation, applied it to a DTO and written a Java 1.6 style annotationProcessor. I can see how to have the annotationProcessor write a new source file, which isn't what I want to do, I cannot see or find out how to have it modify the existing class (ideally just modify the byte code). The modification is actually fairly trivial, all I want the processor to do is to insert a new getter and setter where the name comes from the value of the annotation being processed.
My annotation processor looks like this;
#SupportedSourceVersion(SourceVersion.RELEASE_6)
#SupportedAnnotationTypes({ "com.kn.salog.annotation.AggregateField" })
public class SalogDTOAnnotationProcessor extends AbstractProcessor {
#Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
//do some stuff
}
}
You are looking for "Instrumentation", which is what frameworks like AspectJ do. In this case you have to specify a jar in the command line with the "-agent" option, and then have the possibility to filter all loaded classes. During this filter step you can check for annotations, and modify the bytecode before it gets loaded in the virtual machine. Libraries for doing the actual bytecode modification include "asm", and maybe the highlevel wrappers "cglib" and "javassist". You could even precompile your classes to generate a list of classes which have to be instrumented by you, to make filtering in the beginning a bit faster.
See java.lang.instrumentation for more info.
By design, the annotation processing facility does not allow direct modification of the source code being processed. However, one can generate subclasses of the type being processed or the superclass of the type being processed. With some planning, this does allow some of the effect of modifying the type in question. I've written up an example of how this can fit together; see this blog entry for a more detailed explanation and some sample code.
You have to use internal compiler's classes – some inspiration:
AOP or APT for overriding methods from super classes
RomanNumeralProcessor.java
Java Multiline String
But it is brinkmanship. Your program will compile only on Sun/OpenJDK and there can be problems in future versions (internal API can change). Although once compiled, it is standard bytecode and will run everywhere.
BTW: if you want use it in Eclipse, you should add some special support for it because Eclipse uses non-standard compiler. Your design should be more complex and you should add a level of abstraction to your processor – like Lombok does.
You have to extend the javac compiler for this, which means building your program won't be as portable as a regular application. See http://weblogs.java.net/blog/cayhorstmann/archive/2006/06/say_no_to_prope.html for more details on how someone achieved this.